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

📄 编写 windows 标准控件㈡ .txt

📁 会变语言实现的一些程序
💻 TXT
📖 第 1 页 / 共 3 页
字号:
                    mov [ebx].iMaxWidth,eax
                .endif
                invoke ReleaseDC,hList,ps.hdc
            .endif
            invoke SendMessage,hList,WM_SIZE,0,0
            pop eax         ;返回索引
 
设置项目的信息,如果包含文本,则复制到内存中,并且,计算文本的总长度,与结构中的最大长度比较,更长则替换,之后,WM_SIZE消息发送,水平滚动条自动变化 
        .elseif SDWORD ptr edx>=0 && edx<[ebx].iCount
            mov eax,[edi+edx*4]
            jmp @@SetExistItem
        .endif 
设置一个项目的信息,直接返回对应的地址,并跳转到公共部分 



MLM_GETSTRING             获得字串

        mov MI.imask,MIF_TEXT
        mov MI.cbText,0FFFFh
        mov eax,lParam
        mov MI.lpszText,eax
        invoke SendMessage,hList,MLM_GETITEM,wParam,addr MI 
获得项目的文本,wParam为索引,lParam==指向返回字串的缓存地址 



MLM_GETITEM              ;获得项目数据

        mov eax,MLM_ERROR
        mov esi,lParam
        mov ecx,wParam
        .if SDWORD ptr ecx>=0 && ecx<[ebx].iCount
            mov edi,[ebx].lpItems
            mov edi,[edi+ecx*4]
            .if [esi].imask & MIF_IMAGE
                mov ecx,[edi].MYLIST_ITEM.iImage
                mov [esi].iImage,ecx
            .endif
            .if [esi].imask & MIF_USERDATA
                mov ecx,[edi].MYLIST_ITEM.dwData
                mov [esi].dwData,ecx
            .endif
            mov eax,wParam             ;返回索引
            
            .if [esi].imask & MIF_TEXT
                mov ecx,[edi].MYLIST_ITEM.cbText
                inc ecx
                .if ecx>=[esi].cbText
                    mov ecx,[esi].cbText
                .endif
                push ecx
                invoke lstrcpyn,[esi].lpszText,addr [edi].MYLIST_ITEM.lpText,ecx
                ;如果获得字串,返回大小
                pop eax
            .endif
        .endif
        assume esi:nothing 
获得项目数据,wParam为索引,lParam==指向返回信息的结构地址
成功返回非零值。失败为-1
 



MLM_SETIMAGELIST        设置图像列表

        invoke ParentNotify,hList,MLN_IMAGECHANGED,wParam
        or [ebx].fStyle ,MLFS_SHARED
        mov eax,[ebx].hImage
        mov ecx,wParam
        mov [ebx].hImage,ecx 
设置图像列表,wParam为句柄,lParam==0
返回前一次的图像列表。

函数替换默认的图像列表,并且设置标志”共享的图像列表“,如果不再需要,请删除旧的图像列表。
在替换之前,发送消息给父窗口,因为使用者有可能获得图像列表之后,保存了起来,然后操作它。替换后,通知一下,方便使用者手动更新。
 



MLM_GETIMAGELIST             获得图像列表

       mov eax,[ebx].hImage 
直接返回当前使用的图像列表 


MLM_ADDIMAGE                ;添加图片到图像列表中.返回索引

        xor eax,eax
        .if lParam!=eax
            .if wParam==IMAGE_BITMAP
                invoke CopyImage,lParam,IMAGE_BITMAP,0,0,LR_COPYRETURNORG
                mov edi,eax
                invoke ImageList_Add,[ebx].hImage,lParam,eax
                push eax
                invoke DeleteObject,edi
                pop eax
            .elseif wParam==IMAGE_ICON
                invoke ImageList_AddIcon,[ebx].hImage,lParam
            .endif
        .endif 
添加一个图片或者一个图标到当前图像列表中。
wParam指定格式,lParam指定句柄
成功返回图像索引,项目的图像是直接使用此索引的。失败返回-1
 



MLM_RESTORE        初始化状态

        invoke HeapCreate,HEAP_NO_SERIALIZE,0,0
        .if eax!=0
            mov esi,eax
            invoke HeapAlloc,esi,HEAP_ZERO_MEMORY or HEAP_NO_SERIALIZE,1024*4
            .if eax!=0
                mov [ebx].lpItems,eax
                .if [ebx].hHeap!=0
                    invoke HeapDestroy,[ebx].hHeap
                .endif
                mov [ebx].hHeap,esi
                mov [ebx].cbItems,1024
                xor eax,eax
                mov [ebx].iTop,eax
                mov [ebx].iLeft,eax
                mov [ebx].iMaxWidth,eax
                mov [ebx].iCount,eax
                mov [ebx].iSel,-1
                .if !([ebx].fStyle & MLFS_SHARED) && wParam!=0
                    invoke ImageList_Remove,[ebx].hImage,-1
                .endif
                invoke SendMessage,hList,WM_SIZE,0,0
            .endif
        .endif 
初始化控件,重新创建新堆,新内存,新的图像列表。旧的全部删除。
在这里判断了图像列表是否是共享的,是则不管它。
之后,直接WM_SIZE,之后,滚动条会自动全部设置好。 



MLM_GETITEMRECT        获得项目区域

        mov eax,[ebx].rt.bottom
        xor edx,edx
        div [ebx].iHeight
        .if edx!=0
            inc eax
        .endif
        mov ecx,[ebx].iTop
        add eax,ecx
        .if wParam>=ecx && wParam<=eax
            mov edx,[ebx].iCount
            cmp wParam,edx     ;在可视范围
            jge @@Error
                mov eax,wParam
                sub eax,ecx
                xor edx,edx
                mov ecx,[ebx].iHeight
                mul ecx
                add eax,[ebx].rt.top
                add ecx,eax
                invoke SetRect,lParam,[ebx].rt.left,eax,[ebx].rt.right,ecx
                mov eax,TRUE
        .else
            xor eax,eax
        .endif 
获得指定项目的区域,目标项目必须是在可视客户区内才会成功。
wParam为项目索引,lParam指向RECT结构返回区域坐标
成功非零,失败为0
 



MLM_GETCURSEL        获得当前选择

        mov eax,[ebx].iSel 
直接返回当前选择的索引项目 

MLM_SETCURSEL        设置当前选择

        mov edi,wParam
        .if sdword ptr edi<0 || edi>=[ebx].iCount
            mov edi,-1
        .endif
        .if lParam & MSC_SETFOCUS
            invoke SetFocus,hList
        .endif
        invoke ParentNotify,hList,NMN_SELCHANGING,edi
        .if eax==0
            .if lParam & MSC_SETVISIBLE && edi !=-1
                invoke SendMessage,hList,MLM_ITEMVISIBLE,edi,0
            .endif
            invoke SendMessage,hList,MLM_GETITEMRECT,[ebx].iSel,addr rt
            mov esi,[ebx].iSel
            mov [ebx].iSel,edi
            .if eax==TRUE
                invoke DrawItem,hList,0,ebx,esi,addr rt,fStyle
            .endif
            invoke SendMessage,hList,MLM_GETITEMRECT,[ebx].iSel,addr rt
            .if eax==TRUE
                invoke DrawItem,hList,0,ebx,[ebx].iSel,addr rt,fStyle
            .endif
            invoke UpdateWindow,hList
            invoke ParentNotify,hList,MLN_SELCHANGED,esi
        .endif
        mov eax,edi 
设置当前选择项目.成功返回当前选择。wParam为索引,lParam指定设置风格
如果不是有效的项目索引,将自动设置为未选择状态。

在设置之前,会发送消息给父窗口,如果返回值非零,则取消之后的操作。

否则刷新并设置新的选择索引。这里为什么需要获得区域并自己画呢?这就是初步的无闪烁刷新处理了,如果每次更改之后,都全部刷新,在操作快的时候,容易看出闪动,这里这样处理,就算是重绘了二次,但是不会闪烁。
 


MLM_ITEMVISIBLE         确保指定项目是可见的

        mov edi,wParam
        mov eax,[ebx].rt.bottom
        xor edx,edx
        div [ebx].iHeight
        mov ecx,[ebx].iTop
        mov edx,eax
        add edx,ecx
        .if edi>=ecx && edi<=edx     ;已经是可视的
            xor eax,eax
            jmp @@Ret
        .elseif edi>=edx
            mov ecx,edi
            sub ecx,eax
            inc ecx
        .else
            mov ecx,edi
        .endif
        mov sci.nPos,ecx
        call @@SetScrollPos
        invoke InvalidateRect,hList,0,0
        mov eax,TRUE 
wParam指定索引,判断后,如果项目不可见,将它设置为可见。
如果已经是可见的,返回0,否则返回TRUE 



MLM_SETHEIGHT || uMsg==MLM_GETHEIGHT    设置高度/获得高度

        mov eax,[ebx].iHeight
        .if uMsg==MLM_SETHEIGHT
            mov ecx,lParam
            .if ecx<MIN_HEIGHT
                mov ecx,MIN_HEIGHT
            .endif
            mov [ebx].iHeight,ecx
            invoke SendMessage,hList,WM_SIZE,0,0
        .endif 
设置高度或获得高度,返回以前的高度值。之后WM_SIZE重新设置滚动条。 



MLM_GETCOUNT             获得项目总数

        mov eax,[ebx].iCount 
直接返回当前项目的总个数。0表示没有。 



MLM_SETDATA             设置用户数据

        mov eax,[ebx].dwData
        mov ecx,lParam
        mov [ebx].dwData,ecx 
返回窗口用户数据。注意这里的是窗口数据,而不是项目的。 



MLM_GETDATA             获得窗口数据

        mov eax,[ebx].dwData 
直接返回当前数据 



WM_DESTROY            ;控件销毁

        .if !([ebx].fStyle & MLFS_SHARED)
            invoke ImageList_Destroy,[ebx].hImage
        .endif
        invoke HeapDestroy,[ebx].hHeap
        invoke LocalFree,ebx 
        ;所有使用的内存全部是在这个堆中分配的,只需要销毁这个堆即可.同时,如果图像列表不是共享的,删除它。 


    到这里为止,控件就差不多了。大家可详细地使用一下。参照说明文档,也即是Control.inc文件,即可知道控件是很好用的。几乎不需要特别地学习,只要以前有SDK控件使用经历,花上十来分钟,这个控件你就会用了,费了这么多心思写标准控件,其实是为了方便使用者。

    事实上,本系列的教程,其实没有什么技术含量,对于有基础的朋友来说,这文章不看也罢,直接看代码去了,因为就算是代码,也不过是基础的Windows编程的组合,看几遍,就可以自己动手干了。前面也有说,在这个控件写之前,其实我写的是扩展与增强上一章的控件的,但是思来想去,还是决定再写一个新控件,因为新控件至少还告诉大家如何操作多元素。

    我在考虑,这一章是否是系列的完结,因为我感觉有点费力不讨好,要写得太简单了,没看头,写得太复杂了,初学的朋友也看不懂,最主要是的,写控件涉及到各方各面,如果不解释涉及的部分,感觉不行。如果要解释,那可不是一般的难。。郁闷啊。。。

    下一期,我看情况,如果有好的灵感,我就再接着写一篇,如果实在是不知道写什么,或者说是如何写,就暂时到此为止,有任何问题大家可到论坛提出。最重要的是,如果你真的想写控件,那一定得动手才行。可不是当成泡菜尝过就没了。。。

再留一个习题吧.

    列表控件没有插入操作的功能,添加消息功能,MLM_INSERTADDSTRING,MLM_INSERTITEM,在指定的位置插入项目。

    在项目结构中添加一个新成员,保存项目的状态。然后添加一个窗口风格 MLS_MULSELECT,并实现多选功能。这个有点难度。但是稍想一想,要实现其实不难。呵呵,当然关键在于,这里的变化,需要多个地方更改。练练手吧。增强一下,这个控件就可以直接拿来使用了。呵呵。



--------------------------------------------------------------------------------
<<<上一篇  欢迎访问AoGo汇编小站:http://www.aogosoft.com 下一篇>>>  

⌨️ 快捷键说明

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