zoukankan      html  css  js  c++  java
  • Win32汇编控件的超类化感想

    对于窗口的子类化相信大家并不陌生:基于某一个控件功能,用窗口子类化来实现我们想要的功能!由于控件的封装,我们无法对它进行直接操作修改,但是我们可以截获windows给控件过程发送的消息,从而达到控制控件窗口的目的!对于单个控件的子类化,并不费事,但是我们如果要注册多个这样的控件就麻烦了,于是产生了超类化的思想。

    可以用GetClassInfoEx()来获取现存类的属性,然后修改结构的内容,就可以派生出一个功能不同的类!如下面一段代码:

     .const
    szClass         db      "NewEdit",0
    ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    …………
    _SuperClass     proc
            local   @stWndClass:WNDCLASSEX
            
            ;//////////////////////////////////
            ;  基于 Edit 类建立一个新类:NewEdit
            ;//////////////////////////////////
            mov     @stWndClass.cbSize,sizeof WNDCLASSEX
            invoke  GetClassInfoEx,NULL,CTXT("edit"),addr @stWndClass
            push    @stWndClass.lpfnWndProc
            pop     lpOldProcEdit
            mov     @stWndClass.lpfnWndProc,offset _ProcEdit
            push    hInstance
            pop     @stWndClass.hInstance
            mov     @stWndClass.lpszClassName,offset szClass
            invoke  RegisterClassEx,addr @stWndClass
            ret
            
    _SuperClass     endp

    基于Edit类的NewEdit类就产生了,其中_ProcEdit子程序是NewEdit类的过程函数。这不禁让我想到当初创建windows窗口的时候,每次都要注册一次WNDCLASSEX结构体函数,下面使我们非常熟悉的代码:

    _WinMain        proc
                    local   @stWndClass:WNDCLASSEX
                    local   @stMsg:MSG
    
                    invoke  GetModuleHandle,NULL
                    mov     hInstance,eax
                    invoke  RtlZeroMemory,addr @stWndClass,sizeof @stWndClass
    ;********************************************************************
    ; 注册窗口类
    ;********************************************************************
                    invoke  LoadCursor,0,IDC_ARROW
                    mov     @stWndClass.hCursor,eax
                    push    hInstance
                    pop     @stWndClass.hInstance
                    mov     @stWndClass.cbSize,sizeof WNDCLASSEX
                    mov     @stWndClass.style,CS_HREDRAW or CS_VREDRAW
                    mov     @stWndClass.lpfnWndProc,offset _ProcWinMain
                    mov     @stWndClass.hbrBackground,COLOR_WINDOW + 1
                    mov     @stWndClass.lpszClassName,offset szClassName
                    invoke  RegisterClassEx,addr @stWndClass
    …………

    这岂不也是对于窗口的“子类化”吗?我们可以自定义窗口的背景颜色,光标位图以及主窗口图标!然后调用CreateWindowEx来创建,我想窗口超类化的思想和这里肯定也有些未知的联系(不知道我的思考对不对)!当然也可以在RC文件中用我们超类化好的“NewEdit”,下面是一段演示代码,是针对进制转化超类化出来的,控件中只能输入0~9以及A~F,并自动把小写字母大写,资源文件的定义如下:

    //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    #include        <resource.h>
    //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    #define ICO_MAIN        1000
    #define DLG_MAIN        1000
    //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    ICO_MAIN        ICON    "Main.ico"
    //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    DLG_MAIN DIALOG 190, 180, 126, 20
    STYLE    DS_MODALFRAME | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_POPUP
    CAPTION  "SuperClass"
    FONT     9,"YaHei Consolas Hybrid"
    {
        CONTROL     "",-1,"HexEdit",ES_LEFT | WS_BORDER | WS_TABSTOP,5,5,115,12
    }
    //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

    汇编源代码如下:

    ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
                    .386
                    .model  flat, stdcall
                    option  casemap: none
    ;---------------------------------------------------------------------------------
    include         windows.inc
    include         user32.inc
    includelib      user32.lib
    include         kernel32.inc
    includelib      kernel32.lib
    
    include         macro.asm
    ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    ICO_MAIN        equ     1000
    DLG_MAIN        equ     1000
    ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
                    .data?
    hInstance       dd      ?
    hWinMain        dd      ?
    lpOldProcEdit   dd      ?
                    
                    .const
    szAllowedChar   db      "0123456789ABCDEFabcdef",08h
    szClass         db      "HexEdit",0
    ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
                    .code
    ;--------------------------------------------------------------------------------- 
    _ProcEdit       proc    uses ebx edi esi hWnd, uMsg, wParam, lParam
            
            .if     uMsg == WM_CHAR
                    mov     eax,wParam
                    lea     edi,szAllowedChar
                    mov     ecx,sizeof szAllowedChar
                    cld
                    repnz   scasb
                    .if     ZERO?
                            ;====================将字母转换为大写
                            .if     al > '9'
                                    and     al,not 20h
                            .endif
                            invoke  CallWindowProc,lpOldProcEdit,hWnd,uMsg,eax,lParam
                            ret
                    .endif  
            .else
                    invoke  CallWindowProc,lpOldProcEdit,hWnd,uMsg,wParam,lParam
                    ret
            .endif
            xor     eax,eax
            ret
            
    _ProcEdit       endp
    ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    _SuperClass     proc
            local   @stWndClass:WNDCLASSEX
            
            ;//////////////////////////////////
            ;  基于 Edit 类建立一个新类:HexEdit
            ;//////////////////////////////////
            mov     @stWndClass.cbSize,sizeof WNDCLASSEX
            invoke  GetClassInfoEx,NULL,CTXT("edit"),addr @stWndClass
            push    @stWndClass.lpfnWndProc
            pop     lpOldProcEdit
            mov     @stWndClass.lpfnWndProc,offset _ProcEdit
            push    hInstance
            pop     @stWndClass.hInstance
            mov     @stWndClass.lpszClassName,offset szClass
            invoke  RegisterClassEx,addr @stWndClass
            ret
            
    _SuperClass     endp
    ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    _ProcDlgMain    proc    uses ebx edi esi hWnd, uMsg, wParam, lParam
            
            mov     eax,uMsg
            .if     eax ==  WM_CLOSE
                    invoke  EndDialog,hWnd,NULL
            .else
                    mov     eax,FALSE
                    ret
            .endif
            mov     eax,TRUE
            ret
            
    _ProcDlgMain    endp
    ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    start:
            invoke  GetModuleHandle,NULL
            mov     hInstance,eax
            call    _SuperClass
            invoke  DialogBoxParam,hInstance,DLG_MAIN,NULL,offset _ProcDlgMain,NULL
            invoke  ExitProcess,NULL
    ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
            end     start

    这中间我也学到了很多,老早就从Zoologist的文章中了解到如何去用Spy++去查看窗口属性,以及怎么去截获窗口消息。今天用了下,明白了窗口一些基本的属性,以及看到别的程序一些不知道的风格可以去“截取”,而不必打开MSDN,啃着枯燥的英文!突然想到的一点就是有些程序当光标放在BUTTON上面就变成一个手型,很好奇。通过Spy++研究到可以截获WM_MOUSEMOVE消息来了解光标的活动范围,然后用API函数SetCursor来改变光标形状!这个我没有实验过,感觉中不能实现光标的持续性停留变化。还有一招就是调用API函数SetClassLong,利用GCL_HCURSOR参数来“永久改变”,但后再改回来!麻烦了些,具体还没有实验,调研中……

    -------------------------------------------------------

    kedebug

    Department of Computer Science and Engineering,

    Shanghai Jiao Tong University

    E-mail: kedebug0@gmail.com

    GitHub: http://github.com/kedebug

    -------------------------------------------------------

  • 相关阅读:
    Django ORM查询总结
    Django中settings.py 相关配置说明
    项目完整开发流程
    生产环境中不小心升级了glibc该怎么办?
    提取网页里所有链接的方法
    fofa基本语法
    python爬取豆瓣top250电影源码
    一键清理系统的缓存
    内网隧道搭建---Neo-reGeorg
    若依后台管理系统sql注入和未授权访问
  • 原文地址:https://www.cnblogs.com/kedebug/p/2791756.html
Copyright © 2011-2022 走看看