;===============================================修改说明===============================================

【软件名称】XP记事本(Notepad)
【下载地址】附件(附本文)
【应用平台】Win9x/NT/2000/XP
【软件大小】120K
【软件限制】未修改时,没有工具栏。
【保护方式】--------
【修 改 者】andy00
【修改难度】1/10
【修改说明】只是为了熟悉逆向工程,所以使用静态分析。
【分析工具】Olldbg,计算器
【参考资料】MSDN
【软件简介】--------

;===============================================附加的说明==============================================

    这个程序是接着上一修改的,本文的某些东西如果看不懂请先看这一篇:

    逆向初步,增加XP记事本功能,使用背景色,文字颜色,下划线,删除线

    http://bbs.pediy.com//showthread.php?s=&threadid=23277

    对于比较麻烦的修改,建议大家先弄清流程,搞清楚要哪些函数,哪些变量,然后写出伪代码,划分空闲数据与代码空间,建议两者
各占空间,不要混合.给变量挨个分配空间,非数组的,尽量都分配双字以上,方便管理.最后再动手,不至于手忙脚乱,思路混乱
搞到最后自己都不知道在哪里了,只好放弃.

;===============================================增加的功能分析==========================================

功能1   创建工具条菜单
功能2   创建工具条,能够通过工具条菜单来控制显示/隐藏
....    从文件载入工具条位图资源.这时百toolbar.bmp



;=============================================功能实现需要的信息=======================================

;创建工具条
    
    使用函数CreateToolbarEx或CreateWindowEx,后一个非常麻烦,所以用前一个:
    
HWND CreateToolbarEx(          
    HWND        hwnd,           //父窗口句柄
    DWORD       ws,             //窗口样式
    UINT        wID,            //窗口ID
    int         nBitmaps,       //位图数
    HINSTANCE   hBMInst,        //位图所在的模块,若为NULL,则wBMID必须是有效的位图句柄
    UINT_PTR    wBMID,          //位图在该模块中的句柄
    LPCTBBUTTON lpButtons,      //TBBUTTON结构
    int         iNumButtons,    //工具栏按钮数(包含分隔符)
    int         dxButton,       //按钮宽度
    int         dyButton,       //按钮高度
    int         dxBitmap,       //按钮位图宽度16,24,32...
    int         dyBitmap,       //按钮位图高度16,24,32...
    UINT        uStructSize     //TBBUTTON结构的大小,为14
);

    成功则返回工具条句柄,失败则返回0
    
; 载入工具栏位图

    因为我们是要从文件载入工具栏位图,所以使用函数LoadImage
    
HANDLE LoadImage(         
    HINSTANCE   hinst,          //位图所在模块从文件载入此处为0
    LPCTSTR     lpszName,       //位图文件路径(相对或完整均可)
    UINT        uType,          //图像类型这里是IMAGE_BITMAP
    int         cxDesired,      //位图宽度,为0则按真实大小
    int         cyDesired,      //位图高度,为0则按真实大小
    UINT        fuLoad          //载入方式,从文件载入为LR_LOADFROMFILE
);

    成功返回位图句柄,失败返回0
    
; 删除位图对象
    
    凡是GDI对象,多数要在不使用的时候释放它们的内存,位图对象也是.所以要使用函数DeleteObject删除它
    
BOOL DeleteObject(
  HGDIOBJ       hObject         // 位图句柄
);

    成功返回真,否则返回假
    
; 设置菜单检查标记
    
    使用函数CheckMenuItem

DWORD CheckMenuItem(         
    HMENU       hmenu,          //主菜单句柄
    UINT        uIDCheckItem,   //子菜单ID
    UINT        uCheck          //检查标志,MF_CHECKED(==8)为检查,MF_UNCHECKED(==0)为不检查
);


; 获得主菜单
    
    使用函数
    
HMENU GetMenu(
    HWND        hWnd            //窗口句柄
);

    成功返回菜单句柄,失败返回0
        
; 其它函数

    对于窗口及其大小的操作难免用到这几个函数
    
    GetClientRect,      //获取客户区区域
    MoveWindow,         //移动/设置窗口位置/大小
    ShowWinodw          //显示/隐藏窗口
    
    详细请查阅MSDN
    
; 相关消息
    
    WM_SIZE

        WPARAM wParam
        LPARAM lParam
        
参数说明:

lParam  低字指出了窗口的新的客户区宽度,高字指出了窗口的新的客户区的高度.
    
    WM_COMMAND

        WPARAM wParam
        LPARAM lParam;
参数说明:

wParam  消息状态码,如果是加速键消息,高字为1,如果是菜单消息,高字为0,低字为控件/菜单/加速键ID
lParam  如果是控件消息,则为控件句柄,否则为0 


;=============================================功能实现伪代码============================================

#define ID_TOOLBAR     101      //工具栏ID

TBBUTTON tbButtonsCreate [ ] =  //创建工具栏需要的数据,详细请查阅MSDN                                           
{
    //0,    x,              4,                  0,        0,  0,  0
    {0, IDM_FILE_NEW,       TBSTATE_ENABLED, BTNS_BUTTON, {0},0L, 0},
    {1, IDM_FILE_OPEN,      TBSTATE_ENABLED, BTNS_BUTTON, {0},0L, 0},
    {2, IDM_FILE_SAVE,      TBSTATE_ENABLED, BTNS_BUTTON, {0},0L, 0},
    {3, IDM_FILE_SAVEAS,    TBSTATE_ENABLED, BTNS_BUTTON, {0},0L, 0},
    {4, IDM_FILE_PRINTCFG,  TBSTATE_ENABLED, BTNS_BUTTON, {0},0L, 0},
    {0,     0           ,   TBSTATE_ENABLED, BTNS_SEP,    {0},0L, 0},
    {5, IDM_FILE_PRINTCFG,  TBSTATE_ENABLED, BTNS_BUTTON, {0},0L, 0},
    {6, IDM_FILE_PRINTCFG,  TBSTATE_ENABLED, BTNS_BUTTON, {0},0L, 0},
    {7, IDM_FILE_PRINTCFG,  TBSTATE_ENABLED, BTNS_BUTTON, {0},0L, 0},
    {8, IDM_FILE_PRINTCFG,  TBSTATE_ENABLED, BTNS_BUTTON, {0},0L, 0},
    {9, IDM_FILE_PRINTCFG,  TBSTATE_ENABLED, BTNS_BUTTON, {0},0L, 0},
    {10, IDM_FILE_PRINTCFG, TBSTATE_ENABLED, BTNS_BUTTON, {0},0L, 0},
    {11, IDM_FILE_PRINTCFG, TBSTATE_ENABLED, BTNS_BUTTON, {0},0L, 0},
    {0,     0           ,   TBSTATE_ENABLED, BTNS_SEP,    {0},0L, 0},
    {12, IDM_FILE_PRINTCFG, TBSTATE_ENABLED, BTNS_BUTTON, {0},0L, 0},
    {13, IDM_FILE_PRINTCFG, TBSTATE_ENABLED, BTNS_BUTTON, {0},0L, 0},

};

int             cxEdit
int             cyEdit;
int             yEdit;
int             cyToolBar;
HWND            hWndToolbar,hWndEdit;
BOOL            bShowToolBar=TRUE;
RECT            rcClient;
HMENU           hMenu;
HBITMAP         hToolBarBitmap;
WCHAR           wsBitmap[]="toolbar.bmp";

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    int wmId,       wmEvent;

    switch (message) 
    {
    case WM_CREATE:
        hToolBarBitmap=(HBITMAP)LoadImage(NULL,wcBitmap,IMAGE_BITMAP,0,0,LR_LOADFROMFILE);  //载入位图
        
        hWndToolbar = CreateToolbarEx (hWnd, 
            WS_CHILD | WS_VISIBLE , 
            ID_TOOLBAR, 14, NULL,(UINT)hToolBarBitmap , 
            tbButtonsCreate, 16, 0, 0, 16, 16, sizeof (TBBUTTON));      //创建工具条
        
        hWndEdit    =CreateWindow("edit"/*.其余参数省略...*/);          //创建编辑框
        
        CheckMenuItem(hMenu,IDM_VIEW_TOOLBAR,MF_CHECKED);               //设置检查标志

        break;

    case WM_SIZE:
        cxEdit=LOWORD(lParam);
        cyEdit=HIWORD(lParam);
        
        cyEdit=cyWnd;
        cyToolBar=0;
        yEdit=0;

        if(bShowToolBar)        //如果当前是显示的
        {
            cyEdit-=28;         //编辑框高度减28
            yEdit+=28;          //下移28
            cyToolBar=28;       //工具栏高度28
        }

        MoveWindow(hWndToolbar,0,0,cxEdit,cyToolBar,TRUE);      //调整工具栏窗口
        MoveWindow(hWndEdit,0,yEdit,cxEdit,cyEdit,TRUE);        //调整编辑框窗口

        return TRUE;

    case WM_COMMAND:    
        wmId    = LOWORD(wParam)
        wmEvent = HIWORD(wParam)

        switch (wmId)
        {   
        case IDM_VIEW_TOOLBAR:  //菜单1D==1D

            bShowToolBar=!bShowToolBar;     
            ShowWindow(hWndToolbar,bShowToolBar);       //显示/隐藏工具栏
                        
            CheckMenuItem(hMenu,IDM_VIEW_TOOLBAR,bShowToolBar?MF_CHECKED:MF_UNCHECKED);     //设置/取消检查标志
            
            GetClientRect(hWnd,&rcClient);

            if(bShowToolBar)
            {
                rcClient.top+=30;
            }
            
            MoveWindow(hWndEdit,rcClient.left,rcClient.top,
            rcClient.right-rcClient.left,rcClient.bottom-rcClient.top,TRUE);        //调整编辑框区域
            return TRUE;
        }
        return DefWindowProc(hWnd, message, wParam, lParam);
        
    case WM_DESTROY:
        DeleteObject(hToolBarBitmap);       //删除位图对象
        PostQuitMessage(0);

        break;      
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

注意由于使用函数LoadImageW,必须使用宽字符集,第个字母占两个字节如图:

 

;==========================================根据伪代码分配空间,输入函数====================================

;============================增加输入函数=============================

;需要手动输入的函数

comctl32.dll    CreateToolbarEx     0001408C

;已输入的函数
USEER32.DLL     SendMessageW        01001240
USR32.DLL       ShowWinodw          010011B0
USR32.DLL       MoveWindow          01001220
USR32.DLL       CheckMenuItem       01001248
USR32.DLL       GetClientRect       01001188
USR32.DLL       LoadImageW          010011D4
USR32.DLL       GetMenu             01001264
            
;============================增加程序空间=============================

.andy00     VSize:10000     VOffset:14000   RSize:10000     ROffset:10A00   Flag:E0000060

空间分配

10A00(14000)    11000(14600)  输入表    共600
11100(14700)    19000(1C600)  代码      共7F00
19100(1C700)    1FA00(23000)  数据      共6900  


;============================变量分配================================


;工具条功能变量(1C704->1C914)

变量类型        变量名              文件偏移            虚拟偏移
hWnd ==DWORD PTR DS:[1009830]
HWND            hWndEdit            8438                9838                ; 编辑框句柄,程序已分配
int             cxWnd               19104               1C704               ; 编辑框宽度
int             cyWnd               19108               1C708               ; 编辑框高度
int             yEdit               1910C               1C70C               ; 编辑框最高位置                

int             cyToolBar           19114               1C714               ; 工具条高度    
HWND            hWndToolbar         19118               1C718               ; 工具条句柄
int             iCheckFlag          1911C               1C71C               ; 是否显示工具条
HMENU           hMenu               19120               1C720               ; 主菜单句柄
TBBUTTON[]      tbButtonsCreate     1912C->1926C        1C72C->1C86C        ; 用于创建工具条的数据

COLORREF        crText              19270               1C870               ;颜色字体功能变量
COLORREF        crBkgnd             19274               1C874               ;颜色字体功能变量
HBRUSH          hBrBkgnd            19278               1C878               ;颜色字体功能变量
CHOOSECOLOR     cc                  1927C->1929C        1C87C->1C89C        ;颜色字体功能变量

TCHAR[]         szBitmapName        19280               1C880

COLORREF[]      lpcusColor          192A0->192B0        1C8A0->1C8B0        ;颜色字体功能变量
DWORD           tmp                 192B4               1C8B4               ;颜色字体功能变量

HBITMAP         hBitmap             19300               1C900               ; 工具条位图句柄
RECT            rcClient.left       19304               1C904               ; 客户区的矩形区域
                rcClient.top        19308               1C908               
                rcClient.right      1930C               1C90C
                rcClient.bottom     19310               1C910



准备的工具栏按钮位图


;===========各菜单ID,按在工具栏上从左到右的顺序排列,0为分隔栏=============

打开,新建,保存,另存,打印,空格,查找,剪切,复制,粘贴,撤消1,撤消2,删除,空格,字体,颜色

2   1       3   4   5   0       15  300 301  302    10  10      303 0   21  1C



;===============================================创建工具条=============================================

;找到创建编辑框的地方

0100473A   .  8B45 90           MOV     EAXDWORD PTR SS:[EBP-70]
0100473D   .  53                PUSH    EBX                                     ; /lParam
0100473E   .  FF75 AC           PUSH    DWORD PTR SS:[EBP-54]                   ; |hInst=[EBP-54]
01004741   .  83C0 9C           ADD     EAX, -64                                ; |
01004744   .  6A 0F             PUSH    0F                                      ; |
01004746   .  FF35 30980001     PUSH    DWORD PTR DS:[1009830]                  ; |hParent=hWnd=[1009830]
0100474C   .  50                PUSH    EAX                                     ; |Height
0100474D   .  FF75 8C           PUSH    DWORD PTR SS:[EBP-74]                   ; |Width
01004750   .  A1 50980001       MOV     EAXDWORD PTR DS:[1009850]             ; |
01004755   .  F7D8              NEG     EAX                                     ; |
01004757   .  53                PUSH    EBX                                     ; |Y
01004758   .  1BC0              SBB     EAXEAX                                ; |
0100475A   .  53                PUSH    EBX                                     ; |X
0100475B   .  25 0000F0FF       AND     EAX, FFF00000                           ; |
01004760   .  05 04013050       ADD     EAX, 50300104                           ; |
01004765   .  50                PUSH    EAX                                     ; |Style
01004766   .  56                PUSH    ESI                                     ; |WindowName
01004767   .  68 94170001       PUSH    01001794                                ; |Class = "Edit"
0100476C   .  68 00020000       PUSH    200                                     ; |ExtStyle = WS_EX_CLIENTEDGE
01004771   .  FF15 E0110001     CALL    DWORD PTR DS:[<&USER32.CreateWindowExW>>; \CreateWindowExW
01004777   .  90                NOP
01004778   .  90                NOP
01004779   .- E9 A0E90000       JMP     01014900                                ;跳到初始化画刷的代码
0100477E   .  0F84 2A020000     JE      010049AE
;................
;................
    
    由以上代码分析可以得到: hInst== SS:[EBP-54]
                            hWnd == DWORD PTR DS:[1009830]



01014900    A3 38980001         MOV     DWORD PTR DS:[1009838], EAX             ; hWndEdit
01014905    68 FFFFFF00         PUSH    0FFFFFF                                 ; 白色
0101490A    FF15 5D400101       CALL    DWORD PTR DS:[101405D]                  ; 创建白色画刷CreateSolidBrush
01014910    A3 78C80101         MOV     DWORD PTR DS:[101C878], EAX             ; 保存画刷句柄
01014915    C705 74C80101 FFFFF>MOV     DWORD PTR DS:[101C874], 0FFFFFF         ; 保存背景颜色白色
0101491F    A1 38980001         MOV     EAXDWORD PTR DS:[1009838]             ; 从这里开始添加创建工具条的代码
                                                                                ; 这一句在最后加上
01014924    3BC3                CMP     EAXEBX                                ; 这一句在最后加上
01014926  - E9 53FEFEFF         JMP     0100477E                                ; 这一句在最后加上


;原来创建画刷的部分:

010148FC    A3 38980001         MOV     DWORD PTR DS:[1009838], EAX
01014901    68 FFFFFF00         PUSH    0FFFFFF
01014906    FF15 5D400101       CALL    DWORD PTR DS:[101405D]                  ; GDI32.CreateSolidBrush
0101490C    A3 78C80101         MOV     DWORD PTR DS:[101C878], EAX
01014911    C705 74C80101 FFFFF>MOV     DWORD PTR DS:[101C874], 0FFFFFF
;................
;................

;新加的部分,加载工具栏位图创建工具栏,设置"显示工具栏"iCheckFlag(保存在RVA==1C71C)为"显示"(=MF_CHECKED==8)

0101491B      6A 10               PUSH    10                                      ; /fuLoad=LR_LOADFROMFILE
0101491D      90                  NOP                                             ; |从文件载入 
0101491E      90                  NOP
0101491F      6A 00               PUSH    0                                       ; |cyDesired=0
01014921      6A 00               PUSH    0                                       ; |cxDesired=0
01014923      6A 00               PUSH    0                                       ; |uType=IMAGE_BITMAP
01014925      68 80C80101         PUSH    0101C880                                ; |UNICODE "toolbar.bmp"
0101492A      6A 00               PUSH    0                                       ; |hinst=NULL(从文件载入)
0101492C      FF15 D4110001       CALL    DWORD PTR DS:[<&USER32.LoadImageW>]     ; \LoadImageW

01014932      A3 00C90101         MOV     DWORD PTR DS:[101C900], EAX             ; 保存到hBitmap(RVA==1C900)   
01014937      6A 14               PUSH    14                                      ; /sizof(TBBUTTON)            
01014939      6A 10               PUSH    10                                      ; |dyBitmap=16    
0101493B      6A 10               PUSH    10                                      ; |dxBitmap=16(16*16小图标)
0101493D      6A 00               PUSH    0                                       ; |dyButton默认
0101493F      6A 00               PUSH    0                                       ; |dxButton默认
01014941      6A 10               PUSH    10                                      ; |iNumButtons=10
01014943      68 2CC70101         PUSH    0101C72C                                ; |lpButtons=tbButtons
01014948      FF35 00C90101       PUSH    DWORD PTR DS:[101C900]                  ; |wBMID=hBitmap(这里使用文件载入)
0101494E      6A 00               PUSH    0                                       ; |hBMInst=NULL(要从文件载入) 
01014950      6A 0D               PUSH    0D                                      ; |nBitmap=13
01014952      6A 65               PUSH    65                                      ; |wndID=65
01014954      68 00000050         PUSH    50000000                                ; |wndStyle=WS_CHILD|WS_VISIBLE
01014959      FF35 30980001       PUSH    DWORD PTR DS:[1009830]                  ; |hParent =hWnd
0101495F      FF15 8C400101       CALL    DWORD PTR DS:[101408C]                  ; \CreateToolbarEx
01014965      85C0                TEST    EAXEAX
01014967      74 2B               JE      SHORT 01014994                          ; 创建失败则不进行下面动作交给程序处理
01014969      A3 18C70101         MOV     DWORD PTR DS:[101C718], EAX             ; 保存工具条句柄到hWndToolbar(RVA==1C718)
0101496E      C705 1CC70101 08000>MOV     DWORD PTR DS:[101C71C], 8               ; 设置工具条显示状态为"显示",iCheckFlag=MF_CHECKED

01014978      FF35 30980001       PUSH    DWORD PTR DS:[1009830]                  ; /参数hWnd入栈
0101497E      FF15 64120001       CALL    DWORD PTR DS:[<&USER32.GetMenu>]        ; \GetMenu(hWnd)
01014984      A3 20C70101         MOV     DWORD PTR DS:[101C720], EAX             ; 保存菜单句柄到hMenu(RVA==1C720)

01014989      6A 08               PUSH    8                                       ; uCheckFlag=MF_CHECKED (设置选中标志,一个小勾)
0101498B      6A 1D               PUSH    1D                                      ; 要设置的子菜单,"工具栏"菜单
0101498D      50                  PUSH    EAX                                     ; 菜单句柄hMenu
0101498E      FF15 48120001       CALL    DWORD PTR DS:[<&USER32.CheckMenuItem>]  ; CheckMenuItem(hMenu,1D,MF_CHECKED);

01014994      A1 38980001         MOV     EAXDWORD PTR DS:[1009838]             ; 原来程序的代码
01014999      3BC3                CMP     EAXEBX                                ; 原来程序的代码
0101499B    - E9 DEFDFEFF         JMP     0100477E                                ; 返回原片交给程序处理


;========================================清除位图对象,防止内存泄漏====================================

;直接来到以前清楚画刷的地方

01014860    FF35 78C80101       PUSH    DWORD PTR DS:[101C878]                  ; 画刷句柄
01014866    FF15 68100001       CALL    DWORD PTR DS:[<&GDI32.DeleteObject>]    ; DeleteObject(hBrBkgnd)
0101486C    6A 00               PUSH    0
0101486E    FF15 F4110001       CALL    DWORD PTR DS:[<&USER32.PostQuitMessage>>; USER32.PostQuitMessage
01014874  - E9 44ECFEFF         JMP     010034BD


;把以上代码改为

01014860    FF35 78C80101       PUSH    DWORD PTR DS:[101C878]                  ; 画刷句柄
01014866    FF15 68100001       CALL    DWORD PTR DS:[<&GDI32.DeleteObject>]    ; DeleteObject(hBrBkgnd)
0101486C    FF35 00C90101       PUSH    DWORD PTR DS:[101C900]                  ; 位图句柄
01014872    FF15 68100001       CALL    DWORD PTR DS:[<&GDI32.DeleteObject>]    ; DeleteObject(hBitmap)
01014878    6A 00               PUSH    0
0101487A    FF15 F4110001       CALL    DWORD PTR DS:[<&USER32.PostQuitMessage>>; USER32.PostQuitMessage
01014880  - E9 38ECFEFF         JMP     010034BD


    保存修改,然后运行修改过的程序,这时候,出现了工具条,但是还有问题,任何编辑框的操作都会出现,光栅出现在工具
"内部"的情况,而且这时候,工具条是不能用的.



    这是因为,对编辑框进行的某些操作可能导致程序收到WM_SIZE消息,而记事本处理的WM_SIZE的时候,默认是把编辑框
放到客户区顶端的,所以我们必须处理WM_SIZE消息


;===========================================处理WM_SIZE消息=============================================

;来到WNDPROC

01003429      8BFF              MOV     EDIEDI
0100342B  /.  55                PUSH    EBP
0100342C  |.  8BEC              MOV     EBPESP
0100342E  |.  51                PUSH    ECX
0100342F  |.  51                PUSH    ECX
01003430  |.  56                PUSH    ESI
01003431  |.  8B75 0C           MOV     ESIDWORD PTR SS:[EBP+C]              ; ESI=message
01003434    - E9 67130100       JMP     010147A0                               ; 以前修改的代码,不用关心此处,一会儿会跳回来
01003439      90                NOP
0100343A  |.  5A                POP     EDX
0100343B  |.  0F87 41020000     JA      01003682
01003441  |.  0F84 B7010000     JE      010035FE
01003447  |.  3BF2              CMP     ESIEDX
01003449  |.  0F87 ED000000     JA      0100353C
0100344F  |.  0F84 DB000000     JE      01003530
01003455  |.  8BC6              MOV     EAXESI                                ; EAX=message
01003457  |.  48                DEC     EAX                                     ; message--;
01003458  |.  48                DEC     EAX                                     ; message--;    
01003459  |.  0F84 C7000000     JE      01003526        
0100345F  |.  83E8 03           SUB     EAX, 3                                  ; message-=3;
01003462  |.  74 61             JE      SHORT 010034C5                          ; if(message==WM_SIZE) GOTO 010034c5
010034BD  |>  33C0              XOR     EAXEAX                                ;  Default case of switch 010034CE
010034BF  |> |5F                POP     EDI
010034C0  |. |5E                POP     ESI
010034C1  |. |C9                LEAVE
010034C2  |. |C2 1000           RET     10                                      ; 退出WNDPROC,之前不跳就完了


;WM_SIZE消息的处理过程,从01003462跳过来

010034C5  |> \8B45 10           MOV     EAXDWORD PTR SS:[EBP+10]              ;  从这儿跳到自己的代码,因为我们不关心
010034C8  |.  33F6              XOR     ESIESI                                ;  wParam的值为什么.直接处理WM_SIZE消息
;................
;................                                                                                 


;010034C5-010034C8两句改为

010034C5    -  E9 B0180100        JMP     01014BC0                                ; ===========跳到自己的代码==========
010034CA  |.   2BC6               SUB     EAXESI
010034CC  |.   74 06              JE      SHORT 010034D4                           ;  wParam==SIZE_RESTORED
010034CE  |.   48                 DEC     EAX                                      ;  
010034CF  |.   74 49              JE      SHORT 0100351A                              ;  wParam==   SIZE_MINIMIZED
010034D1  |.   48                 DEC     EAX                                      
010034D2  |.^  75 E9              JNZ     SHORT 010034BD                           ;  if(wParam!=SIZE_MAXIMIZED)goto 010034BD

010034BD  |>   33C0               XOR     EAXEAX                                 ;  Default case of switch 010034CE
010034BF  |>   |5F                POP     EDI
010034C0  |.   |5E                POP     ESI
010034C1  |.   |C9                LEAVE
010034C2  |.   |C2 1000           RET     10                                      ; 退出WNDPROC,之前不跳就完了


;
01014BC0      50                  PUSH    EAX
01014BC1      8B45 14             MOV     EAXDWORD PTR SS:[EBP+14]              ; EAX=lParam
01014BC4      25 FFFF0000         AND     EAX, 0FFFF                              ; EAX=LOWORD(lParam),LOWARD(lParam)==窗口现在宽度
01014BC9      A3 04C70101         MOV     DWORD PTR DS:[101C704], EAX             ; cxEdit
01014BCE      8B45 14             MOV     EAXDWORD PTR SS:[EBP+14]              ; EAX=lParam
01014BD1      C1E8 10             SHR     EAX, 10                                 ; EAX=HIWORD(lParam),HIWARD(lParam)==窗口现在高度
01014BD4      A3 08C70101         MOV     DWORD PTR DS:[101C708], EAX             ; cyEdit=HIWORD(lParam)
01014BD9      833D 1CC70101 08    CMP     DWORD PTR DS:[101C71C], 8
01014BE0      75 21               JNZ     SHORT 01014C03                          ; if(iCheckFlag!=MF_CHECKED) goto 01014C03
01014BE2      90                  NOP                                             ; 当前没有显示则跳到01014c03      
01014BE3      90                  NOP
01014BE4      90                  NOP
01014BE5      90                  NOP                                             ; 如果现在工具条显示的,执行以下动作
01014BE6      832D 08C70101 1C    SUB     DWORD PTR DS:[101C708], 1C              ; 编辑框高度-=3D
01014BED      C705 0CC70101 1C000>MOV     DWORD PTR DS:[101C70C], 1C              ; 编辑框最高位置yEdit=30D
01014BF7      C705 14C70101 1C000>MOV     DWORD PTR DS:[101C714], 1C              ; 工具条高度cyToolbar==30D
01014C01      EB 14               JMP     SHORT 01014C17                          ; 如果iCheckFlag==0当前没有显示工具条,
01014C03      C705 0CC70101 00000>MOV     DWORD PTR DS:[101C70C], 0               ; 则编辑框从客户区最高位置yEdit=0
01014C0D      C705 14C70101 00000>MOV     DWORD PTR DS:[101C714], 0               ; 工具条高度设为0,cyToolbar=0

01014C17      6A 01               PUSH    1                                       ; /bRepaint=TRUE
01014C19      FF35 14C70101       PUSH    DWORD PTR DS:[101C714]                  ; |cyToolbar
01014C1F      FF35 04C70101       PUSH    DWORD PTR DS:[101C704]                  ; |cxEdit
01014C25      6A 00               PUSH    0                                       ; |yToolbar
01014C27      6A 00               PUSH    0                                       ; |xToolbar
01014C29      FF35 18C70101       PUSH    DWORD PTR DS:[101C718]                  ; |hWndToolbar
01014C2F      FF15 20120001       CALL    DWORD PTR DS:[<&USER32.MoveWindow>]     ; \MoveWindow按参数调整窗口大小位置

01014C35      6A 01               PUSH    1                                       ; /bRepaint=TRUE
01014C37      FF35 08C70101       PUSH    DWORD PTR DS:[101C708]                  ; |cyEdit
01014C3D      FF35 04C70101       PUSH    DWORD PTR DS:[101C704]                  ; |cxEdit
01014C43      FF35 0CC70101       PUSH    DWORD PTR DS:[101C70C]                  ; |yEdit
01014C49      6A 00               PUSH    0                                       ; |xEdit
01014C4B      FF35 38980001       PUSH    DWORD PTR DS:[1009838]                  ; |hEdit
01014C51      FF15 20120001       CALL    DWORD PTR DS:[<&USER32.MoveWindow>]     ; \MoveWindow按参数调整编辑框窗口大小位置

01014C57      58                  POP     EAX                                     ; 还原EAX现场     
01014C58      8B45 10             MOV     EAXDWORD PTR SS:[EBP+10]              ; 以下动作退出WNDPROC,平衡堆栈,返回1
01014C5B      33F6                XOR     ESIESI
01014C5D      B8 01000000         MOV     EAX, 1
01014C62      5F                  POP     EDI
01014C63      5E                  POP     ESI
01014C64      C9                  LEAVE
01014C65      C2 1000             RET     10

    现在不管怎么样对编辑框操作,都不会有问题了,"工具栏"都老老实实地在那儿,但是,如果我们不想它在那儿怎么办呢?当我们选择
"查看"菜单下的"工具栏"菜单时,让它显示/隐藏工具栏.

    实现这个功能,当然要处理,"工具栏"菜单的WM_COMMAND消息    

;=========================================处理菜单"工具栏"消息=========================================

010149C1    83FF 1C             CMP     EDI, 1C
010149C4    0F85 A2000000       JNZ     01014A6C
010149CA    A1 38980001         MOV     EAXDWORD PTR DS:[1009838]
010149CF    A3 80C80101         MOV     DWORD PTR DS:[101C880], EAX
010149D4    C705 7CC80101 24000>MOV     DWORD PTR DS:[101C87C], 24
010149DE    C705 84C80101 00000>MOV     DWORD PTR DS:[101C884], 0
010149E8    C705 88C80101 0000F>MOV     DWORD PTR DS:[101C888], 0FF0000
010149F2    C705 8CC80101 00AE0>MOV     DWORD PTR DS:[101C88C], 0100AE00
010149FC    C705 90C80101 01000>MOV     DWORD PTR DS:[101C890], 1
01014A06    C705 94C80101 00000>MOV     DWORD PTR DS:[101C894], 0
01014A10    C705 98C80101 00000>MOV     DWORD PTR DS:[101C898], 0
01014A1A    C705 9CC80101 00000>MOV     DWORD PTR DS:[101C89C], 0
01014A24    50                  PUSH    EAX
01014A25    68 7CC80101         PUSH    0101C87C
01014A2A    FF15 1C400101       CALL    DWORD PTR DS:[<&comdlg32.ChooseColorW>] ; comdlg32.ChooseColorW
01014A30    09C0                OR      EAXEAX
01014A32    74 37               JE      SHORT 01014A6B
01014A34    A1 88C80101         MOV     EAXDWORD PTR DS:[101C888]
01014A39    A3 74C80101         MOV     DWORD PTR DS:[101C874], EAX
01014A3E    FF35 78C80101       PUSH    DWORD PTR DS:[101C878]
01014A44    FF15 68100001       CALL    DWORD PTR DS:[<&GDI32.DeleteObject>]    ; GDI32.DeleteObject
01014A4A    FF35 74C80101       PUSH    DWORD PTR DS:[101C874]
01014A50    FF15 5D400101       CALL    DWORD PTR DS:[101405D]                  ; GDI32.CreateSolidBrush
01014A56    A3 78C80101         MOV     DWORD PTR DS:[101C878], EAX
01014A5B    6A 01               PUSH    1
01014A5D    6A 00               PUSH    0
01014A5F    FF35 38980001       PUSH    DWORD PTR DS:[1009838]
01014A65    FF15 24120001       CALL    DWORD PTR DS:[<&USER32.InvalidateRect>] ; USER32.InvalidateRect
01014A6B    58                  POP     EAX
01014A6C    83FF 40             CMP     EDI, 40
01014A6F    8995 F0FDFFFF       MOV     DWORD PTR SS:[EBP-210], EDX
01014A75  - E9 49E1FEFF         JMP     01002BC3



更改为:

;原有代码大部分在http://bbs.pediy.com//showthread.php?s=&threadid=23277有详细说明,此处不作解释

010149C1    83FF 1C             CMP     EDI, 1C
010149C4    0F85 A2000000       JNZ     01014A6C
010149CA    50                  PUSH    EAX
010149CB    A1 38980001         MOV     EAXDWORD PTR DS:[1009838]
010149D0    A3 80C80101         MOV     DWORD PTR DS:[101C880], EAX
010149D5    C705 7CC80101 24000>MOV     DWORD PTR DS:[101C87C], 24
010149DF    C705 84C80101 00000>MOV     DWORD PTR DS:[101C884], 0
010149E9    C705 88C80101 0000F>MOV     DWORD PTR DS:[101C888], 0FF0000
010149F3    C705 8CC80101 00AE0>MOV     DWORD PTR DS:[101C88C], 0100AE00
010149FD    C705 90C80101 01000>MOV     DWORD PTR DS:[101C890], 1
01014A07    C705 94C80101 00000>MOV     DWORD PTR DS:[101C894], 0
01014A11    C705 98C80101 00000>MOV     DWORD PTR DS:[101C898], 0
01014A1B    C705 9CC80101 00000>MOV     DWORD PTR DS:[101C89C], 0
01014A25    68 7CC80101         PUSH    0101C87C
01014A2A    FF15 1C400101       CALL    DWORD PTR DS:[<&comdlg32.ChooseColorW>] ; comdlg32.ChooseColorW
01014A30    09C0                OR      EAXEAX
01014A32    74 37               JE      SHORT 01014A6B
01014A34    A1 88C80101         MOV     EAXDWORD PTR DS:[101C888]
01014A39    A3 74C80101         MOV     DWORD PTR DS:[101C874], EAX
01014A3E    FF35 78C80101       PUSH    DWORD PTR DS:[101C878]
01014A44    FF15 68100001       CALL    DWORD PTR DS:[<&GDI32.DeleteObject>]    ; GDI32.DeleteObject
01014A4A    FF35 74C80101       PUSH    DWORD PTR DS:[101C874]
01014A50    FF15 5D400101       CALL    DWORD PTR DS:[101405D]                  ; GDI32.CreateSolidBrush
01014A56    A3 78C80101         MOV     DWORD PTR DS:[101C878], EAX
01014A5B    6A 01               PUSH    1
01014A5D    6A 00               PUSH    0
01014A5F    FF35 38980001       PUSH    DWORD PTR DS:[1009838]
01014A65    FF15 24120001       CALL    DWORD PTR DS:[<&USER32.InvalidateRect>] ; USER32.InvalidateRect
01014A6B    58                  POP     EAX
                                                        
                                                                                
; 判断是否点击的"工具栏"菜单
                
01014A6C    83FF 1D             CMP     EDI, 1D                                 ; 是否点击的"工具栏"菜单                            
01014A6F    0F85 A0000000       JNZ     01014B15                                ; 不是则交张程序处理

; 以下新加代码用于"显示","隐藏"工具栏

01014A75    50                  PUSH    EAX                                     ; 保存EAX现场
01014A76    833D 1CC70101 08    CMP     DWORD PTR DS:[101C71C], 8
01014A7D    74 0E               JE      SHORT 01014A8D                          ; 如果当前是显示,则跳到隐藏代码
01014A7F    C705 1CC70101 08000>MOV     DWORD PTR DS:[101C71C], 8               ; 否则显示,置显示状态为显示
01014A89    6A 01               PUSH    1                                       ; nCmdShow=SW_SHOW
01014A8B    EB 0C               JMP     SHORT 01014A99      
01014A8D    C705 1CC70101 00000>MOV     DWORD PTR DS:[101C71C], 0
01014A97    6A 00               PUSH    0                                       ; nCmdSHOW=SW_HIDE
01014A99    FF35 18C70101       PUSH    DWORD PTR DS:[101C718]
01014A9F    FF15 B0110001       CALL    DWORD PTR DS:[<&USER32.ShowWindow>]     ; ShowWindow(hWndToolbar,nCmdShow)
01014AA5    FF35 1CC70101       PUSH    DWORD PTR DS:[101C71C]                  ; 显示状态=
01014AAB    6A 1D               PUSH    1D                                      ; 菜单ID
01014AAD    FF35 20C70101       PUSH    DWORD PTR DS:[101C720]                  ; hMenu
01014AB3    FF15 48120001       CALL    DWORD PTR DS:[<&USER32.CheckMenuItem>]  ; CheckMenuItem
01014AB9    68 04C90101         PUSH    0101C904                                ; /&RECT
01014ABE    FF35 30980001       PUSH    DWORD PTR DS:[1009830]                  ; |hWnd 
01014AC4    FF15 88110001       CALL    DWORD PTR DS:[<&USER32.GetClientRect>]  ; \GetClientRect(hWnd,&RECT)
01014ACA    833D 1CC70101 08    CMP     DWORD PTR DS:[101C71C], 8               ;
01014AD1    75 07               JNZ     SHORT 01014ADA                          ; 不显示则不处理直接MoveWindow
01014AD3    8305 08C90101 1E    ADD     DWORD PTR DS:[101C908], 1E              ; 如果显示,则编辑框位置下移1C
01014ADA    6A 01               PUSH    1                                       ; bRepaint=TRUE;
01014ADC    A1 10C90101         MOV     EAXDWORD PTR DS:[101C910]
01014AE1    2B05 08C90101       SUB     EAXDWORD PTR DS:[101C908]
01014AE7    57                  PUSH    EDI                                     
01014AE8    56                  PUSH    ESI                                     ; 保存寄存器现场
01014AE9    8BF8                MOV     EDIEAX
01014AEB    A1 0CC90101         MOV     EAXDWORD PTR DS:[101C90C]
01014AF0    2B05 04C90101       SUB     EAXDWORD PTR DS:[101C904]
01014AF6    8BF0                MOV     ESIEAX                                ;       
01014AF8    57                  PUSH    EDI                                     ; rc.bottom-rc.top      
01014AF9    56                  PUSH    ESI                                     ; rc.right-rc.left
01014AFA    FF35 08C90101       PUSH    DWORD PTR DS:[101C908]                  ; rc.right
01014B00    FF35 04C90101       PUSH    DWORD PTR DS:[101C904]                  ; rc.left
01014B06    FF35 38980001       PUSH    DWORD PTR DS:[1009838]                  ; hWndEdit
01014B0C    FF15 20120001       CALL    DWORD PTR DS:[<&USER32.MoveWindow>]     ; MoveWindow
01014B12    5E                  POP     ESI                                     
01014B13    5F                  POP     EDI                                     
01014B14    58                  POP     EAX                                     ; 还原寄存器现场

;原有代码
01014B15    83FF 40             CMP     EDI, 40
01014B18    8995 F0FDFFFF       MOV     DWORD PTR SS:[EBP-210], EDX             ; 被修改的代码还原
01014B1E  - E9 A0E0FEFF         JMP     01002BC3                                ; 交给原程序处理


    现在保存所有的修改,然后运行程序,"工具栏"已经能正常工作了,并能设置检查标志.是不是一切都OK了呢?
    
    现在如果我们点击"自动换行"或者"状态栏"菜单,编辑框跑到工具栏下面去,这个是因为记事本对"自动换行""状态栏"两个菜单
命令的处理,也是默认把编辑框放到客户区最高处的,如果工具栏此是时显示状态的,则会出现上面的BUG



    所以必须处理这两个命令消息.
    
;========================================处理菜单"自动换行"(ID=20)消息=====================================

; 跟踪WM_COMMAND消息处理过程

01002BBE   .- E9 FE1D0100       JMP     010149C1                                ; 这是以前修改的不用理它,一会儿会跳回来
01002BC3      90                NOP
01002BC4      90                NOP
01002BC5      90                NOP
01002BC6      90                NOP
01002BC7   .  0F8F F9060000     JG      010032C6
01002BCD   .  0F84 DB060000     JE      010032AE
01002BD3   .  83FF 15           CMP     EDI, 15                                 ;  Switch (cases 1..21)
01002BD6   .  0F8F CE020000     JG      01002EAA                                ;  因为20>15此处必跳
;................
;................

;01002BD6跳到此处

01002EAA   > \83FF 1A           CMP     EDI, 1A                                 ; 20>1A 此处必跳
01002EAD   .  0F8F 66010000     JG      01003019
;................
;................

;01002EAD跳到此处

01003019   > \6A 1B             PUSH    1B                                       
0100301B   .  5B                POP     EBX                                      ; EBX=1B
0100301C   .  2BFB              SUB     EDIEBX                                 ; wParam-=1B
0100301E   .  0F84 F7010000     JE      0100321B                                 
01003024   .  83EF 05           SUB     EDI, 5                                   ; wParam-=5;
01003027   .  0F84 11010000     JE      0100313E                                 ; wParam==20(是"自动换行"菜单") 跳     
;................
;................


;01003027跳到此处,"自动换行"菜单的处理代码

0100313E   > \A1 50980001       MOV     EAXDWORD PTR DS:[1009850]             ;  Case 20 of switch 01002BD3
01003143   .  F7D8              NEG     EAX
01003145   .  1BC0              SBB     EAXEAX
01003147   .  25 00001000       AND     EAX, 100000
0100314C   .  05 04012050       ADD     EAX, 50200104
01003151   .  50                PUSH    EAX                                     ; /Arg1
01003152   .  E8 EA290000       CALL    01005B41                                ; \01005B41,处理自动换行菜单
;................
;................

;跟到这里,发现用户选择了"自动换行"菜单,记事本会在这里重新创建编辑框,搞不懂为什么要这么做....

01005C11  |.  57                PUSH    EDI                                     ; /lParam
01005C12  |.  FF35 80AB0001     PUSH    DWORD PTR DS:[100AB80]                  ; |hInst = 01000000
01005C18  |.  6A 0F             PUSH    0F                                      ; |hMenu = 0000000F
01005C1A  |.  FF35 30980001     PUSH    DWORD PTR DS:[1009830]                  ; |hParent = 009509CA ('无标题 - 记事本',class='Notepad')
01005C20  |.  FF75 D4           PUSH    DWORD PTR SS:[EBP-2C]                   ; |Height  高度
01005C23  |.  FF75 D0           PUSH    DWORD PTR SS:[EBP-30]                   ; |Width
01005C26  |.  57                PUSH    EDI                                     ; |Y       最高位置,默认是0
01005C27  |.  57                PUSH    EDI                                     ; |X = 0
01005C28  |.  FF75 08           PUSH    DWORD PTR SS:[EBP+8]                    ; |Style
01005C2B  |.  68 94130001       PUSH    01001394                                ; |WindowName = ""
01005C30  |.  68 94170001       PUSH    01001794                                ; |Class = "Edit"
01005C35  |.  68 00020000       PUSH    200                                     ; |ExtStyle = WS_EX_CLIENTEDGE
01005C3A  |.  FF15 E0110001     CALL    DWORD PTR DS:[<&USER32.CreateWindowExW>>; \CreateWindowExW
;................
;................


        分析以上代码,我们只需要更改创建编辑框时的两个参数,编辑框高度和编辑框的最高位置,在这里是这两句

;需要修改的代码

01005C20  |.  FF75 D4           PUSH    DWORD PTR SS:[EBP-2C]                   ; |高度
01005C26  |.  57                PUSH    EDI                                     ; |最高位置,默认是0

        如果当前工具栏状态是"显示",则需要更改它们,如果不是,则不需要更改.必须修改跳转到我们的判断代码

        
;在这里我们修改 01005C1A,因为必须在高度入栈之前修改它们.多余字节以NOP填充
    
01005C1A      - E9 91F00000       JMP     01014CB0
01005C1F        90                NOP
01005C20    |.  FF75 D4           PUSH    DWORD PTR SS:[EBP-2C]                   ; 高度
01005C23        FF75 D0           PUSH    DWORD PTR SS:[EBP-30]
01005C26        57                PUSH    EDI                                     ; 最高位置
01005C27        57                PUSH    EDI
01005C28        FF75 08           PUSH    DWORD PTR SS:[EBP+8]
01005C2B    |.  68 94130001       PUSH    01001394                                ; |WindowName = ""
01005C30    |.  68 94170001       PUSH    01001794                                ; |Class = "Edit"
01005C35    |.  68 00020000       PUSH    200                                     ; |ExtStyle = WS_EX_CLIENTEDGE
01005C3A    |.  FF15 E0110001     CALL    DWORD PTR DS:[<&USER32.CreateWindowExW>>; \CreateWindowExW        
;................
;................

;01005C1A跳到此处,用于判断是否需要更改高度与最高位置

01014CB0      A3 84C80101         MOV     DWORD PTR DS:[101C884], EAX             ; 保存EAX现场,这里不能PUSH EAX
01014CB5      FF35 30980001       PUSH    DWORD PTR DS:[1009830]                  ; 被修改的代码还原
01014CBB      833D 1CC70101 08    CMP     DWORD PTR DS:[101C71C], 8               ; 开始判断工具栏显示状态
01014CC2      75 0F               JNZ     SHORT 01014CD3                          ; 不相等则跳
01014CC4      90                  NOP
01014CC5      90                  NOP
01014CC6      90                  NOP
01014CC7      90                  NOP
01014CC8      836D D4 1C          SUB     DWORD PTR SS:[EBP-2C], 1C               ; 显示则高度减去1C
01014CCC      B8 1C000000         MOV     EAX, 1C                                 ; 最高位置+1C(往下移)
01014CD1      EB 02               JMP     SHORT 01014CD5
01014CD3      33C0                XOR     EAXEAX                                ; 不显示则不修改直接入栈
01014CD5      FF75 D4             PUSH    DWORD PTR SS:[EBP-2C]
01014CD8      FF75 D0             PUSH    DWORD PTR SS:[EBP-30]                  
01014CDB      50                  PUSH    EAX                                     ; 最高位置入栈
01014CDC      57                  PUSH    EDI
01014CDD      A1 84C80101         MOV     EAXDWORD PTR DS:[101C884]             ; 还原EAX现场
01014CE2    - E9 410FFFFF         JMP     01005C28                                ; 跳回原来的创建编辑框代码



;=======================================处理菜单"状态栏"(==1B)消息========================================

;跟踪到WNDPROC里处理"状态栏"菜单的代码

01003019     > \6A 1B             PUSH    1B    
0100301B     .  5B                POP     EBX                                    ; EBX=1B
0100301C     .  2BFB              SUB     EDIEBX                               ; wParam-=1B
0100301E     .  0F84 F7010000     JE      0100321B                               ; 点击了"状态栏"此处必跳
;................
;................

;从0100321b一路跟踪,可以来到这儿

01003273     .  2B85 E4FDFFFF     SUB     EAXDWORD PTR SS:[EBP-21C]
01003279     .  33F6              XOR     ESIESI
0100327B     .  50                PUSH    EAX                                     ; /Arg2==hegiht
0100327C     .  8B85 E8FDFFFF     MOV     EAXDWORD PTR SS:[EBP-218]             ; |
01003282     .  2B85 E0FDFFFF     SUB     EAXDWORD PTR SS:[EBP-220]             ; |
01003288     .  46                INC     ESI                                     ; |
01003289     .  50                PUSH    EAX                                     ; |Arg1=width
0100328A     .  8935 40980001     MOV     DWORD PTR DS:[1009840], ESI             ; |
01003290     .  E8 4BE7FFFF       CALL    010019E0                                ; \Notepad_.010019E0
;................
;................

01001A01    |.  2305 E0A60001     AND     EAXDWORD PTR DS:[100A6E0]
01001A07    |.  6A 01             PUSH    1                                       ; /Repaint = TRUE
01001A09    |.  2BC8              SUB     ECXEAX                                ; |
01001A0B    |.  51                PUSH    ECX                                     ; |Height======从这里跳=========
01001A0C    |.  FF75 08           PUSH    DWORD PTR SS:[EBP+8]                    ; |Width
01001A0F    |.  6A 00             PUSH    0                                       ; |Y = 0
01001A11    |.  6A 00             PUSH    0                                       ; |X = 0
01001A13    |.  FF35 38980001     PUSH    DWORD PTR DS:[1009838]                  ; |hWnd = 01680E64 (class='Edit',parent=01A60E30)
01001A19    |.  FF15 20120001     CALL    DWORD PTR DS:[<&USER32.MoveWindow>]     ; \MoveWindow
01001A1F    |.  5D                POP     EBP
01001A20    \.  C2 0800           RET     8


01001A0B      - E9 F0320100       JMP     01014D00                                ;==========跳到自己的代码========
01001A10        90                NOP
01001A11    |.  6A 00             PUSH    0                                       ; |X = 0
01001A13    |.  FF35 38980001     PUSH    DWORD PTR DS:[1009838]                  ; |hWnd = NULL
01001A19    |.  FF15 20120001     CALL    DWORD PTR DS:[<&USER32.MoveWindow>]     ; \MoveWindow
01001A1F    |.  5D                POP     EBP
01001A20    \.  C2 0800           RET     8


;01001A0B跳到此处,根据显示状态处理编辑框高度与最高位置

01014D00      833D 1CC70101 08    CMP     DWORD PTR DS:[101C71C], 8
01014D07      75 12               JNZ     SHORT 01014D1B                          ; 如果当前是不显示的则不处理
01014D09      90                  NOP
01014D0A      90                  NOP
01014D0B      90                  NOP
01014D0C      90                  NOP
01014D0D      83E9 1C             SUB     ECX, 1C                                 ; 当前是显示的则编辑高度减1C
01014D10      51                  PUSH    ECX                                     ; 高度入栈
01014D11      FF75 08             PUSH    DWORD PTR SS:[EBP+8]                    ; |Width
01014D14      6A 1C               PUSH    1C                                      ; 编辑框最高位置设为1C
01014D16    - E9 F6CCFEFF         JMP     01001A11                                ; 跳回原处
01014D1B      51                  PUSH    ECX
01014D1C      FF75 08             PUSH    DWORD PTR SS:[EBP+8]                    ; |Width当前是不显示的            
01014D1F      6A 00               PUSH    0                                       ; 则编辑框最高位置为0
01014D21    - E9 EBCCFEFF         JMP     01001A11                                ; 跳回原处

    现在一切都没有问题了如图
    
    
    
    ;=====THE !END======
    
;=========================================QQ:41086722=================================================

发现任何问题或者有任何建议请交流...
附件下载:notepad_modified_toolbar.rar

  • 标 题: 答复
  • 作 者:qyc
  • 时 间:2006-03-30 22:03

爽//精华//学习啊//近连几日学习楼主的文章来/
再一次更新楼主修改版/小Q再一次以17521方法加入TOP与窗口透明功能
上一次是以http://bbs.pediy.com/showthread.php?threadid=22877
加上TOP/保留
这次是加17521写的DLL功能插件(窗口透明),在完全不知到17521的方法下加入/
过程序引用peansen的:记事本功能增加方案
http://bbs.pediy.com/showthread.php?threadid=17376 
取精华处:
导出这个函数,注意这个函数是_cdecl的。原因后面我会讲述。
中断RegisterClassExW函数,很容易到这里
01004521   |.  8945 FC           mov dword ptr ss:[ebp-4],eax
01004524   |.  8D45 D0           lea eax,dword ptr ss:[ebp-30]
01004527   |.  50                push eax                                        ; /pWndClassEx,下面的mov是对其进行赋值
01004528   |.  C745 F4 01000000  mov dword ptr ss:[ebp-C],1                      ; |
0100452F   |.  8975 E4           mov dword ptr ss:[ebp-1C],esi                   ; |
01004532   |.  C745 F8 20900001  mov dword ptr ss:[ebp-8],NOTEPAD.01009020       ; |UNICODE "Notepad"
01004539       C745 D8 29340001  mov dword ptr ss:[ebp-28],NOTEPAD.01003429//这是消息处理过程的赋值
01004540   |.  C745 F0 06000000  mov dword ptr ss:[ebp-10],6                     ; |
01004547   |.  897D D4           mov dword ptr ss:[ebp-2C],edi                   ; |
0100454A   |.  897D DC           mov dword ptr ss:[ebp-24],edi                   ; |
0100454D   |.  897D E0           mov dword ptr ss:[ebp-20],edi                   ; |
01004550   |.  FF15 D0110001     call dword ptr ds:[<&USER32.RegisterClassExW>]  ; \RegisterClassExW

我想这个结构在windows编程中是很重要的一部分,那个WndClassEx结构看看msdn就更清楚了。
接着我们看看消息处理过程部分
01003421   \.  C2 0800           retn 8
01003424       CC                int3-------------------将从这里开始消息处理,只是一个简单的call
01003425       CC                int3
01003426       CC                int3
01003427       CC                int3
01003428       CC                int3
01003429       8BFF              mov edi,edi-------------消息处理过程是从这里开始的
0100342B   /.  55                push ebp
0100342C   |.  8BEC              mov ebp,esp
0100342E   |.  51                push ecx
0100342F   |.  51                push ecx
01003430   |.  56                push esi
01003431   |.  8B75 0C           mov esi,dword ptr ss:[ebp+C]
01003434   |.  83FE 1C           cmp esi,1C                                      ;  Switch (cases 2..8001)

利用5个int3和mov edi,edi共7个字节,改写一个call指令
----------------------------------------------关于mov edi,edi--抄的
MOV EDI,EDI is indeed a 2-byte no-op that is there to enable hot-patching.   It enables the application of a hot-fix to a function without a need for a reboot, or even a restart of a running application.   Instead, at runtime, the 2-byte NOP is replaced by a short jump to a long jump instruction that jumps to the hot-fix function.   A 2-byte instruction is required so that when patching the instruction pointer will not point in a middle of an instruction.
------------------------------------------------------------------------
call dword ptr [1013018](共六个,后面不一个nop)
然后修改01004539处的赋值mov dword ptr ss:[ebp-28],NOTEPAD.01003429(改成01003424)

用LordPE查看17521的plug.dll
发现只导入一个Plug含数
现在在要改的版本加入/调用接口:00024032(以你的机子而定)
以peansen的:记事本功能增加方案即可
  现在这个记事本真正的好用多了/现在正与楼主谈给记事本加个自动隐藏功能呢/