⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 编写 windows 标准控件㈡ .txt

📁 会变语言实现的一些程序
💻 TXT
📖 第 1 页 / 共 3 页
字号:

WM_KILLFOCUS        ;失去焦点

        invoke ParentNotify,hList,MLN_KILLFOCUS,wParam
        and [ebx].fStyle ,not MLFS_FOCUS
        invoke InvalidateRect,hList,0,TRUE 
同上。只不过是去掉风格。 


WM_STYLECHANGED        ;风格更改的

        mov esi,lParam
        assume esi:ptr STYLESTRUCT
        .if ([esi].styleOld & WS_VSCROLL) && !([esi].styleNew & WS_VSCROLL)
            ;去掉滚动条
            invoke ShowScrollBar,hList,SB_VERT,0
        .elseif !([esi].styleOld & WS_VSCROLL) && ([esi].styleNew & WS_VSCROLL)
            invoke ShowScrollBar,hList,SB_VERT,TRUE
        .endif
        .if ([esi].styleOld & WS_HSCROLL) && !([esi].styleNew & WS_HSCROLL)
            ;去掉
            invoke ShowScrollBar,hList,SB_HORZ,0
        .elseif !([esi].styleOld & WS_HSCROLL) && ([esi].styleNew & WS_HSCROLL)
            ;添加
            invoke ShowScrollBar,hList,SB_HORZ,TRUE
        .endif
        invoke GetClientRect,hList,addr [ebx].rt
        invoke SetWindowPos,hList,0,0,0,0,0,SWP_NOSIZE or SWP_NOMOVE or SWP_NOZORDER or SWP_DRAWFRAME
        invoke InvalidateRect,hList,0,TRUE         ;刷新 
当窗口的风格变化时,这个消息将被接收。
通过旧风格包含,新风格未包含判定为去掉。旧风格没有,而新风格有,则为加上。当然如果只是单独判断风格是否存在,这也是可行的。
重新获得客户区域是因为当非客户区变化后(滚动条显示/不显示),是不会有WM_SIZE消息的。我们手动重新获得。
然后刷新非客户区域,这样滚动条才会显示/隐藏 



WM_MOUSEWHEEL        鼠标滚轮

        mov eax,wParam
        shr eax,16
        movsx eax,ax
        .if SDWORD ptr eax<0             ;向上滚动滚轮
            invoke SendMessage,hList,WM_VSCROLL,SB_LINEDOWN,0
        .elseif SDWORD ptr eax>0    ;向下滚动滚轮
            invoke SendMessage,hList,WM_VSCROLL,SB_LINEUP,0
        .endif 
直接调用滚动消息。唯一需要注意的是,高16位是表示方向,而它是一个有符号数,所以扩展成32位时,必须使用Movsx. 


WM_VSCROLL             垂直滚动条

        mov sci.cbSize,sizeof SCROLLINFO
        mov sci.fMask,SIF_ALL
        invoke GetScrollInfo,hList,SB_VERT,addr sci
        mov edi,sci.nPos
        mov eax,wParam
        and eax,0ffffh
        .if eax==SB_THUMBTRACK
            mov ecx,sci.nTrackPos
            mov sci.nPos,ecx
        .elseif eax==SB_TOP
            mov eax,sci.nMin
            mov sci.nPos,eax
        .elseif eax==SB_BOTTOM
            mov eax,sci.nMax
            mov sci.nPos,eax
        .elseif eax==SB_LINEUP
            dec sci.nPos
        .elseif eax==SB_LINEDOWN
            inc sci.nPos
        .elseif eax==SB_PAGEUP
            mov eax,sci.nPage
            dec eax
            sub sci.nPos,eax
        .elseif eax==SB_PAGEDOWN
            mov eax,sci.nPage
            dec eax
            add sci.nPos,eax
        .endif
        mov sci.fMask ,SIF_POS or SIF_DISABLENOSCROLL
        invoke SetScrollInfo,hList,SB_VERT, addr sci, TRUE
        invoke GetScrollInfo,hList, SB_VERT, addr sci
        mov esi,sci.nPos
        .if esi != edi
            mov [ebx].iTop,esi

            .if esi>edi
                mov eax,esi
                sub eax,edi
                imul eax,[ebx].iHeight
                neg eax
                invoke ScrollWindow,hList,0,ecx,0,0
            .else
                mov eax,edi
                sub eax,esi
                imul eax,[ebx].iHeight
                invoke ScrollWindow,hList,0,eax,0,0
            .endif
        .endif 
滚动条消息的处理,设置之后,再获取是为了判断是否是正确的位置,比如如果手动滚动,使用了-1,而滚动条设置函数SetScrollInfo会自动限定在范围内,这个时候再获得的就是正确的位置。
然后通过滚动的相差位置,用ScrollWindow向相反的方向滚动一样的距离。无闪烁滚动,在重绘内容相当复杂,或者用时长时必须要滚动之后再自己重绘.本控件重绘时费的时间相当少,可以直接 Invalidatrect,相差不大.肉眼是看不出来的. 


WM_HSCROLL           水平滚动

        mov sci.cbSize,sizeof SCROLLINFO
        mov sci.fMask,SIF_ALL
        invoke GetScrollInfo,hList,SB_HORZ,addr sci
        mov edi,sci.nPos
        mov eax,wParam
        and eax,0ffffh
        .if eax==SB_THUMBTRACK
            mov eax,sci.nTrackPos
            mov sci.nPos,eax
        .elseif eax==SB_LEFT
            mov eax,sci.nMin
            mov sci.nPos,eax
        .elseif eax==SB_RIGHT
            mov eax,sci.nMax
            mov sci.nPos,eax
        .elseif eax==SB_LINEUP
            mov eax,[ebx].iWidth
            sub sci.nPos,eax
        .elseif eax==SB_LINEDOWN
            mov eax,[ebx].iWidth
            add sci.nPos,eax
        .elseif eax==SB_PAGEUP
            mov eax,sci.nPage
            shr eax,1
            sub sci.nPos,eax
        .elseif eax==SB_PAGEDOWN
            mov eax,sci.nPage
            shr eax,1
            add sci.nPos,eax
        .endif
        mov sci.fMask ,SIF_POS or SIF_DISABLENOSCROLL
        invoke SetScrollInfo,hList,SB_HORZ, addr sci,TRUE
        invoke GetScrollInfo,hList, SB_HORZ, addr sci
        mov eax,sci.nPos
        .if eax != edi
            mov [ebx].iLeft,eax
            invoke InvalidateRect,hList,0,0
        .endif 
同上 


WM_GETDLGCODE     对话框处理

        .if fStyle & MLS_CLASS
            mov eax,DLGC_WANTALLKEYS  需要所有按键处理
        .else
            mov eax,DLGC_WANTARROWS    只需要方向键
        .endif 
这个消息只在对话框中有效,并且是被动的。默认需要方向键,别的交给对话框处理。如果有MLS_CLASS风格,则处理所有的键。
控件其实并没有处理除方向之外的键,所以这个风格其实是多余的,但是你可以在WM_KEYDOWN消息中处理像VK_RETURN/VK_TAB/VK_SPACE之类的键,做一个判断,这样当有这个风格时,你的处理就可以用了。 


WM_SETFONT       设置字体

        mov eax,[ebx].hFont
        push eax
        mov ecx,wParam
        mov [ebx].hFont,ecx
        invoke GetDC,hList
        mov ps.hdc,eax
        invoke SelectObject,ps.hdc,[ebx].hFont
        invoke GetTextExtentPoint32,ps.hdc,CTXT("W"),1,addr p
        mov eax,p.y
        .if eax<MIN_HEIGHT
            mov eax,MIN_HEIGHT
        .endif
        mov [ebx].iHeight,eax
        mov eax,p.x
        mov [ebx].iWidth,eax
        invoke ReleaseDC,hList,ps.hdc
        pop eax 
设置控件显示的字体,并且根据字体的大小,来自动设置高度与字宽。其中字宽在水平滚动时使用。而高度则是项目使用。
字体的设置一般是在创建时,尤其在对话框中,在创建之后会自动发送,之后除非手动设置是不会再有。所以,单独设置项目高度时注意一下。 



WM_GETFONT            获得字体

       mov eax,[ebx].hFont 
获得当前使用的字体 

 

控件自定义消息

MLM_ADDSTRING        

        mov MI.imask,MIF_TEXT or MIF_IMAGE
        invoke lstrlen,lParam
        mov MI.cbText,eax
        mov eax,lParam
        mov MI.lpszText,eax
        mov eax,wParam
        mov MI.iImage,eax
        invoke SendMessage,hList,MLM_SETITEM,-1,addr MI 
添加一个项目,wParam是图形索引,-1表示不显示,lParam指向字符串

设置好参数,真正添加的功能在MLM_SETITEM消息中。 



MLM_DELETESTRING

        mov edi,[ebx].lpItems
        mov esi,wParam
        .if sdword ptr esi>=0 && esi<[ebx].iCount
            invoke HeapFree,[ebx].hHeap,HEAP_NO_SERIALIZE,[edi+esi*4]
            ;移动数组内存块
            mov eax,[ebx].iCount
            sub eax,esi
            shl eax,2
            invoke RtlMoveMemory,addr [edi+esi*4],addr [edi+esi*4+4],eax
            dec [ebx].iCount
            invoke SendMessage,hList,WM_SIZE,0,0
        .endif 
删除一个项目,wParam为索引,lParam==0
直接释放内存,然后移动数组内存
 



MLM_SETITEM                 ;添加或设置项目数据

wParam==-1时,表示添加一个新项目,否则是修改对应索引的项目。lParam指向ML_ITEM结构
成功返回索引值,失败返回-1

MIF_TEXT        equ 1h
MIF_IMAGE       equ 2h
MIF_USERDATA    equ 4h

ML_ITEM struct
    imask     dd ?    ;MIF_*
    cbText    dd ?
    lpszText  dd ?
    iImage    dd ?
    dwData    dd ?
ML_ITEM ends
imask标识哪些成员可用。MIF_TEXT时,cbText,lpszText可用。MIF_IMAGE时,iImage可用。MIF_USERDATA包含时,dwData有用。
 
        mov eax,MLM_ERROR
        mov esi,lParam
        mov edi,[ebx].lpItems
        assume esi:ptr ML_ITEM
        mov edx,wParam
        .if edx==-1
            mov eax,[ebx].iCount
            inc eax
            .if eax>=[ebx].cbItems    ;数组太小,重新分配
                add eax,1024
                shl eax,2
                invoke HeapReAlloc,[ebx].hHeap,HEAP_NO_SERIALIZE or HEAP_ZERO_MEMORY,[ebx].lpItems,eax
                .if eax==0
                    @@:
                    dec eax
                    jmp @@Ret
                .endif
                mov [ebx].lpItems,eax
                mov edi,eax
                add [ebx].cbItems,1024
            .endif 
判断如果是添加,则比较数组是否还够用,否则重新分配内存,比原来大1024个项目。 
            xor eax,eax
            .if [esi].imask & MIF_TEXT
                cmp [esi].cbText,0ffffh        ;字串不能超过FFFFh大小
                jae @B
                mov eax,[esi].cbText
            .endif
            add eax,sizeof MYLIST_ITEM
            .if eax<0FFh
                mov eax,0FFh                     ;最小为0FFh
            .endif
            invoke HeapAlloc,[ebx].hHeap,HEAP_NO_SERIALIZE or HEAP_ZERO_MEMORY,eax
            test eax,eax
            jz @B        
然后分配项目内存,它是根据字串的长度来分配的,但是大不能超过0FFFF个字节。 
            @@SetExistItem:
            .if [esi].imask & MIF_IMAGE
                mov ecx,[esi].iImage
                mov [eax].MYLIST_ITEM.iImage,ecx
            .else
                mov [eax].MYLIST_ITEM.iImage,-1
            .endif
            .if [esi].imask & MIF_USERDATA
                mov ecx,[esi].dwData
                mov [eax].MYLIST_ITEM.dwData,ecx
            .endif
            .if wParam==-1
                mov ecx,[ebx].iCount
                push ecx
                mov [edi+ecx*4],eax
                inc [ebx].iCount
            .else
                push edx
            .endif
            .if [esi].imask & MIF_TEXT
                mov ecx,[esi].cbText
                mov [eax].MYLIST_ITEM.cbText,ecx
                invoke lstrcpy,addr [eax].MYLIST_ITEM.lpText,[esi].lpszText
                invoke GetDC,hList
                mov ps.hdc,eax
                invoke SelectObject,ps.hdc,[ebx].hFont
                invoke GetTextExtentPoint32,ps.hdc,[esi].lpszText,[esi].cbText,addr p
                mov eax,p.x
                .if eax>[ebx].iMaxWidth

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -