• win32汇编-窗口 对话框 (三)


    创建窗口

                    .386
    
                     .model flat,stdcall
    
                     option casemap:none
    
    ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    
    ; Include 文件定义
    
    ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    
    include          windows.inc
    
    include          gdi32.inc
    
    includelib       gdi32.lib
    
    include          user32.inc
    
    includelib       user32.lib
    
    include          kernel32.inc
    
    includelib       kernel32.lib
    
    ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    
    ; 数据段
    
    ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    
                     .data?
    
    hInstance        dd         ?
    
    hWinMain         dd         ?
    
     
    
                     .const
    
    szClassName      db    'MyClass',0
    
    szCaptionMain    db    'My first Window !',0
    
    szText           db    'Win32 Assembly, Simple and powerful !',0
    
    ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    
    ; 代码段
    
    ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    
                     .code
    
    ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    
    ; 窗口过程
    
    ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    
    _ProcWinMain     proc  uses ebx edi esi,hWnd,uMsg,wParam,lParam
    
                     local @stPs:PAINTSTRUCT
    
                     local @stRect:RECT
    
                     local @hDc
    
     
    
                     mov   eax,uMsg
    
    ;********************************************************************
    
                     .if      eax ==    WM_PAINT
    
                              invoke    BeginPaint,hWnd,addr @stPs
    
                              mov       @hDc,eax
    
     
    
                              invoke    GetClientRect,hWnd,addr @stRect
    
                              invoke    DrawText,@hDc,addr szText,-1,
    
                                       addr @stRect,
    
                                       DT_SINGLELINE or DT_CENTER or DT_VCENTER
    
     
    
                              invoke    EndPaint,hWnd,addr @stPs
    
    ;********************************************************************
    
                     .elseif  eax ==    WM_CLOSE
    
                              invoke    DestroyWindow,hWinMain
    
                              invoke    PostQuitMessage,NULL
    
    ;********************************************************************
    
                     .else
    
                              invoke    DefWindowProc,hWnd,uMsg,wParam,lParam
    
                                       ret
    
                              .endif
    
    ;********************************************************************
    
                     xor      eax,eax
    
                     ret
    
     
    
    _ProcWinMain     endp
    
    ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    
    _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
    
    ;********************************************************************
    
    ; 建立并显示窗口
    
    ;********************************************************************
    
                     invoke   CreateWindowEx,WS_EX_CLIENTEDGE,
    
                              offset szClassName,offset szCaptionMain,
    
                              WS_OVERLAPPEDWINDOW,
    
                              100,100,600,400,
    
                              NULL,NULL,hInstance,NULL
    
                     mov      hWinMain,eax
    
                     invoke   ShowWindow,hWinMain,SW_SHOWNORMAL
    
                     invoke   UpdateWindow,hWinMain
    
    ;********************************************************************
    
    ; 消息循环
    
    ;********************************************************************
    
                     .while   TRUE
    
                              invoke    GetMessage,addr @stMsg,NULL,0,0
    
                              .break    .if eax  == 0
    
                              invoke    TranslateMessage,addr @stMsg
    
                              invoke    DispatchMessage,addr @stMsg
    
                     .endw
    
                     ret
    
     
    
    _WinMain         endp
    
    ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    
    start:
    
                     call     _WinMain
    
                     invoke   ExitProcess,NULL
    
    ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    
                     end      start
    View Code

    前面是顺序下来的几个API:

    GetModuleHandle RtlZeroMemory LoadCursor  RegisterClassEx

    CreateWindowEx ShowWindow UpdateWindow

    调用模块

    如果使用参数NULL调用GetModuleHandle,那么得到的是调用者本模块的句柄

    invoke  GetModuleHandle,NULL

    mov     hInstance,eax

    ChildWindowFromPoint来获得编辑子窗口的句柄。

    锁定了最后的目标即记事本中的编辑子窗口后,程序用PostMessage向它发送消息,根据字符串的长度,用一个循环每次发送一个WM_CHAR消息,WM_CHAR消息的wParam和lParam的含义是:

    wParam = chCharCode    // wParam是键值

    lParam = lKeyData      // lParam是键数据(重复次数)

    程序中用mov eax,al将键值扩展到参数所需的32位,当做wParam参数发送,lParam为1,表示键的重复次数为1次,

    模态对话框

     .386
    
                  .model flat, stdcall
    
                  option casemap :none
    
    ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    
    ; Include 文件定义
    
    ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    
    include       windows.inc
    
    include       user32.inc
    
    includelib    user32.lib
    
    include       kernel32.inc
    
    includelib    kernel32.lib
    
    ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    
    ; Equ 等值定义
    
    ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    
    ICO_MAIN      equ        1000h    ;图标
    
    DLG_MAIN      equ        1
    
    ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    
    ; 数据段
    
    ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    
                  .data?
    
    hInstance     dd         ?
    
    ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    
    ; 代码段
    
    ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    
                  .code
    
    _ProcDlgMain  proc       uses ebx edi esi hWnd,wMsg,wParam,lParam
    
     
    
                  mov        eax,wMsg
    
                  .if        eax == WM_CLOSE
    
                             invoke   EndDialog,hWnd,NULL
    
                  .elseif    eax == WM_INITDIALOG
    
                             invoke   LoadIcon,hInstance,ICO_MAIN
    
                             invoke   SendMessage,hWnd,WM_SETICON,ICON_BIG,eax
    
                  .elseif    eax == WM_COMMAND
    
                             mov      eax,wParam
    
                             .if      ax == IDOK
    
                                      invoke EndDialog,hWnd,NULL
    
                  .endif
    
                  .else
    
                             mov      eax,FALSE
    
                             ret
    
                  .endif                 
    
                  mov        eax,TRUE
    
                  ret
    
                  
    
    _ProcDlgMain  endp
    
    ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    
    start:
    
                  invoke     GetModuleHandle,NULL
    
                  mov        hInstance,eax
    
                  invoke     DialogBoxParam,hInstance,DLG_MAIN,
    
                             NULL,offset _ProcDlgMain,NULL
    
                  invoke     ExitProcess,NULL
    
    ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    
                  end        start
    View Code

    创建模态对话框的函数是DialogBoxParam,它的使用方法是:

    invoke  DialogBoxParam,hInstance,lpTemplateName,hWndParent,

             lpDialogFunc,dwInitParam

     

    要结束模态对话框,必须在对话框过程的WM_CLOSE消息中使用EndDialog函数:

     

    invoke  EndDialog,hDlg,dwResult

     

    非模态对话框

    创建非模态对话框的函数是CreateDialogParam,它的参数定义和DialogBoxParam一模一样:

    invoke  CreateDialogParam,hInstance,lpTemplateName,hWndParent,

             lpDialogFunc,dwInitParam

    mov hDlg,eax

     区别

    非模态对话框模板的风格是否定义WS_VISIBLE决定了是否显示对话框窗口。如果定义了则显示,没有的话,则程序需要在以后自行调用ShowWindow来显示它;而DialogBoxParam函数不管是否定义了WS_VISIBLE风格都会显示对话框。

       CreateDialogParam在建立对话框窗口后直接返回,返回值是对话框窗口的句柄;而DialogBoxParam要在对话框关闭后才返回,返回值是EndDialog中的dwResult参数。

       在CreateDialogParam返回后,应用程序在自己的消息循环中获取对话框消息,所以如果要用非模态对话框做程序的主窗口,消息循环的代码还是要写的;而DialogBoxParam是使用Windows为它内建的消息循环。

       关闭非模态对话框使用DestroyWindow函数,注意在这里不要用EndDialog函数。

    话框过程和窗口过程的输入参数是一样的,也是:

    DialogProc  proc    hwndDlg,uMsg,wParam,lParam

    _ProcDlgMain    proc     uses ebx edi esi hWnd,wMsg,wParam,lParam
    
     
    
                    mov      eax,wMsg
    
                    .if      eax == WM_CLOSE
    
                             ;模态对话框用EndDialog关闭
    
                             ;非模态对话框用DestroyWindow关闭
    
                    .elseif  eax == WM_INITDIALOG
    
                             ;初始化代码
    
                    .elseif  eax == WM_COMMAND
    
                             ;子窗口控件发送的消息
    
                             ;wParam的低16位为子窗口控件ID
    
                    .elseif  eax == WM_XXXX
    
                             ;处理其他需要处理的消息
    
                    .else
    
                             mov      eax,FALSE
    
                             ret
    
                    .endif      
    
                    mov      eax,TRUE
    
                    ret
    
                    
    
    _ProcDlgMain    endp
    View Code

     对话框过程和普通的窗口过程在使用上有以下区别:

       窗口过程对应于不同的消息有各种不同含义的返回值,而对话框过程返回BOOL类型的值,返回TRUE表示已经处理了某条消息,返回FALSE表示没有处理。“对话框管理器”代码会根据返回值决定是否继续处理某一条消息(惟一的例外是WM_INITDIALOG消息)。
    
    ●   对于不处理的消息,不需要调用DefWindowProc来处理,这事情由“对话框管理器”来做。
    
    “对话框管理器”不会把WM_CREATE消息转发给对话框过程,取而代之,它会以WM_INITDIALOG消息来调用对话框过程,程序可以在这里进行一些初始化的操作,WM_INITDIALOG消息的返回值有点特殊,如果程序想自行设置输入焦点,那么可以用SetFocus函数把输入焦点设置到需要的子窗口控件上,然后返回FALSE;如果返回TRUE的话,那么Windows会自动将输入焦点设置到第一个有WS_TABSTOP的子窗口控件上。
    
    对话框过程在WM_COMMAND消息中处理子窗口控件发送的命令,当用户在对话框中按下了按钮,输入文字或选择复选框等操作时,子窗口控件会向对话框过程发送WM_COMMAND消息,wParam是子窗口控件的ID,如例子程序中处理“退出”按钮的消息,在里面用EndDialog函数关闭对话框。
    
    对话框窗口的标题栏上默认没有定义图标,如果要像普通窗口一样显示一个图标,那么可以像例子程序中那样,在WM_INITDIALOG中用WM_SETICON消息来设置。
    View Code

     子窗口句柄

    有一个函数可以从ID中获取子窗口句柄:

    invoke  GetDlgItem,hDlg,dwIDDlgItem

    mov hDlgItem,eax

    函数的输入参数是对话框句柄和ID值,返回值是子窗口句柄;反过来,有两种方法可以从子窗口句柄获取ID

    1 invoke  GetDlgCtrlID,hWndCtrl   ;输入子窗口句柄,返回值是控件ID

    2 invoke  GetWindowLong,hWndCtrl,GWL_ID

    当需要向控件发送消息的时候,当然可以先用GetDlgItem获取子窗口句柄再用SendMessage函数,但有一个函数更为简便:

    invoke  SendDlgItemMessage,hDlg,dwIDDlgItem,Msg,wParam,lParam

    这个函数可以直接向控件发送消息,只需要在参数中指定对话框句柄和子窗口ID(注意:并没有PostDlgItemMessage这样的函数!)。

    下一焦点位置

    如果要想知道在一个控件上按下了Tab键或Shift+Tab键会跳到哪一个控件上去,也就是说下一个或上一个Tab停留位在哪里,可以使用GetNextDlgTabItem函数:

    invoke  GetNextDlgTabItem,hDlg,hCtl,bPrevious

    .if     eax

             mov hWinNext,eax

    .endif

    其中的bPrevious参数指定了搜索的方向;与之相似,使用GetNextDlgGroupItem 函数可以返回下一个分组的位置:

    invoke  GetNextDlgGroupItem,hDlg,hCtl,bPrevious

    .if     eax

             mov hWinNext,eax

    .endif

     

    查看一个单选钮或复选框是否被选中可以用下面的函数来检测:

     

    invoke  IsDlgButtonChecked,hDlg,nIDButton

     

    函数的返回值可能是BST_CHECKED(选中状态),BST_INDETERMINATE(3态复选框的灰化状态)或BST_UNCHECKED(未选中状态)。也可以用向子窗口控件发送BM_GETCHECK消息的方法来检测,返回值和上面的函数是一样的。

     

    如果想设置单选钮或复选框的状态,可以使用下面的语句:

     

    invoke  CheckDlgButton,hDlg,nIDButton,uCheck

     

    参数uCheck用BST_CHECKED,BST_INDETERMINATE或BST_UNCHECKED来表示需要设置的状态,含义同上。向控件发送BM_SETCHECK消息也可以取得同样的效果,这时消息的wParam中放置需要设置的状态。

    针对单选钮有一个专用函数:

    invoke  CheckRadioButton,hDlg,

             nIDFirstButton,nIDLastButton,nIDCheckButton

     

    这个函数把ID在nIDFirstButton和nIDLastButton之间的单选钮全部设置为非选中状态,只有nIDCheckButton是选中状态,当然在使用中要注意将这一批ID定义为连续的数值。

    如果还嫌CheckRadioButton有点麻烦,还有一种最简单的办法——使用自动单选钮,同组的AUTORADIOBUTTON会随着用户选中一个而自动清除其他单选钮的状态,所以在程序中只需要在初始化的时候预设一次,其他时间就可以不必关心设置问题了,以后惟一用到的就是调用IsDlgButtonChecked检查状态了。

    对于文本框,文本长度超过边界的时候默认是自动换行的,但如果同时指定SS_SIMPLE风格的话,就不会自动换行。读者可以在程序中用SetWindowText或发送WM_SETTEXT消息来动态改变显示的文本,同样,也可以用GetWindowText或发送WM_GETTEXT消息来获取其中的文本。

    要获取编辑框中的文本有多种方法,可以用GetWindowText,也可以用发送WM_GETTEXT消息的办法,要设置文本,同样可以用SetWindowText或发送WM_SETTEXT,但最简便的办法还是使用下面的函数:

    invoke   GetDlgItemText,hDlg,nIDDlgItem,lpString,nMaxCount   ;取文本

    invoke   SetDlgItemText,hDlg,nIDDlgItem,lpString             ;设置文本

     

    在实际使用中,经常要在文本编辑控件中输入输出数值型参数,将文本转换为数值比较麻烦,把数值转换为文本也要经过一个wsprintf调用,为了简化操作,Windows提供了两个函数来处理这个问题:

     

    invoke   SetDlgItemInt,hDlg,nIDDlgItem,uValue,bSigned           ;取控件中的数值

     

    invoke   GetDlgItemInt,hDlg,nIDDlgItem,lpTranslated,bSigned ;设置控件中的数值

     

    使用文本编辑控件的时候,文本的长度也是个需要注意的问题。如果控件的宽度定义得过窄,当字符填充到最右边的时候,编辑框就不允许继续输入了,为了继续输入并让文本自动卷动,可以指定WS_HSCROLL风格;反之,定义WS_HSCROLL风格后输入文本的长度不受限制又不好,那么可以用向控件发送EM_LIMITTEXT消息的方法来设定最大长度。下面的例子将IDC_EDIT的输入最大长度定为10个字符:

     

    invoke SendDlgItemMessage,hDlg,IDC_EDIT,EM_LIMITTEXT,10,NULL

     

    另外,有时候可能需要把编辑框设置为只读的(和灰化不同,灰化的编辑框中文本无法进行任何操作,包括卷动操作,而只读的仅仅是不能修改),要把初始状态定义为只读的,只需在定义语句中加上ES_READONLY风格,在程序中需要动态改变只读状态可以发送EM_SETREADONLY消息,下面的第一句把编辑框设为只读,第二句把编辑框改回到可写状态:

     

    invoke SendDlgItemMessage,hDlg,IDC_EDIT,EM_SETREADONLY,TRUE,NULL ;只读

     

    invoke SendDlgItemMessage,hDlg,IDC_EDIT,EM_SETREADONLY,FALSE,NULL    ;可写

     

    文本编辑框在默认状态下是单行的,也可以通过加上ES_MULTILINE风格变成多行的,这时可以同时加上WS_VSCROLL风格显示一个垂直方向的滚动条。

     

    滚动条有水平和垂直两种,默认的SCROLLBAR语句定义的是水平的滚动条,它的默认风格是SBS_HORZ,例子程序中用下面的语句定义了一个水平滚动条:

     

    SCROLLBAR IDC_SCROLL, 6, 118, 125, 10

     

    如果要定义垂直的滚动条,那么要指明SBS_VERT风格:

     

    SCROLLBAR IDC_SCROLL, x, y, 宽度, 高度,SBS_VERT

     

    和其他子窗口控件发送WM_COMMAND消息不同,水平滚动条向对话框窗口发送WM_HSCROLL消息,而垂直滚动条则发送WM_VSCROLL消息,所以针对两种方式的滚动条要分别处理不同的消息。

     

    WM_xSCROLL消息的参数如下所示:

     

    wParam的低16位= nScrollCode        ;动作码

     

    wParam的高16位= nPos       ;滚动条当前位置

     

    lParam   hwndScrollBar      ;滚动条控件的窗口句柄

     

    其中nScrollCode代表了滚动条的当前动作,定义值及其含义如下:

     

       SB_BOTTOM                   滚动条移到了最下/右边。

     

       SB_ENDSCROLL             用户停止了滚动动作。

     

       SB_THUMBPOSITION     滚动条被拖动到某处。

     

       SB_THUMBTRACK          滚动条在拖动中。

     

       SB_TOP                          滚动条移到了最上/左边。

     

       SB_LINELEFT                 滚动条左移了一格(对于水平滚动条)。

     

       SB_LINERIGHT               滚动条右移了一格(对于水平滚动条)。

     

       SB_PAGELEFT                滚动条左移了一页(对于水平滚动条)。

     

       SB_PAGERIGHT              滚动条右移了一页(对于水平滚动条)。

     

       SB_LINEDOWN               滚动条下移了一格(对于垂直滚动条)。

     

       SB_LINEUP                     滚动条上移了一格(对于垂直滚动条)。

     

       SB_PAGEDOWN              滚动条下移了一页(对于垂直滚动条)。

     

       SB_PAGEUP                    滚动条上移了一页(对于垂直滚动条)。

     

    nPos的值只有当动作码是SB_THUMBPOSITION或SB_THUMBTRACK时才有效,其他的时候为0,图5.7示出了鼠标点击滚动条各处时对应的nScrollCode。

    当计算好新位置的时候要将位置设置回去,用户才会看到滚动条移动了,方法是向滚动条发送SBM_SETPOS消息:

    invoke   SendDlgItemMessage,hWnd,IDC_SCROLL,SBM_SETPOS,dwPos,TRUE

    最后一个参数为TRUE表示设置后重新绘画滚动条。

    在初始化的时候,要给滚动条发送SBM_SETRANGE消息来设定滚动范围:

    invoke   SendDlgItemMessage,hWnd,IDC_SCROLL,SBM_SETRANGE,最小值,最大值

    如果需要获取滚动条的信息,可以尝试发送下面两个消息:SBM_GETPOS可以获取滚动条的当前位置,也就是上一次用SBM_SETPOS设置的值;SBM_GETRANGE可以获取滚动的范围,也就是用SBM_SETRANGE设置的值。

    使用组合框

    顾名思义,组合框是一个“组合”起来的东西,它由一个可供选择的列表和一个可供输入的edit类组合而成。组合框让用户既可以自己输入文本,也可以选择列表中的某一项当做输入。用不同的风格定义可以产生3种类型的组合框,如图5.8所示。左边的是CBS_SIMPLE风格的组合框,它的上面可以输入文本,下面的列表可供选择预设文本;中间的是CBS_DROPDOWN风格的组合框,上面同样可以输入文本,但下面的列表是下拉式的,平时处于收起状态,点击编辑框右边的三角形才会拉下来;右边的是CBS_DROPDOWNLIST风格的组合框,它仅是一个下拉的选择框,上面的框中不允许输入文字。

    组合框中还有几种常用的、可以附加的风格:

       CBS_AUTOHSCROLL      输入过长的文本时输入框自动卷动。

       CBS_LOWERCASE          自动将所有的文本转换成小写。

       CBS_SORT               自动将插入的文本项排序。

       CBS_UPPERCASE     自动将所有的文本转换成大写。

     

    组合框中列表框部分的文字添加、项目的选择等操作都是通过发送消息来完成的,主要的消息如表5.5所示。

    5.5  组合框的消息

    消    息

    Wparam

    lParam

    说    明

    CB_ADDSTRING

    0

    字符串地址

    把一个字符串添加到列表中

    CB_INSERTSTRING

    位置索引

    字符串地址

    把一个字符串插入到列表中

    CB_FINDSTRING

    开始查找的位置索引

    查找的字符串

    在列表中查找以lParam字符串开头的项,找到则返回位置索引,未找到则返回CB_ERR

    CB_FINDSTRINGEXACT

    位置索引

    查找的字符串

    精确查找字符串

    CB_DELETESTRING

    位置索引

    0

    删除一个列表项

    CB_RESETCONTENT

    0

    0

    删除所有的列表项

     

    消    息

    Wparam

    lParam

    说    明

    CB_GETLBTEXT

    位置索引

    缓冲区地址

    获取指定列表项的字符串,缓冲区必须足够大

    CB_GETLBTEXTLEN

    位置索引

    0

    获取指定列表项的字符串长度

    CB_GETCOUNT

    0

    0

    获取列表项的总项数

    CB_SETCURSEL

    位置索引

    0

    选中一个列表项,并将列表项中的文字拷贝到编辑控件中

    CB_SELECTSTRING

    开始查找的位置索引

    字符串地址

    查找以lParam指定的字符串开始的列表项,如果找到则选中它并将字符串拷贝到编辑控件中

    CB_GETCURSEL

    0

    0

    获取当前选中的位置索引,没有选中的项目则返回CB_ERR

    CB_SHOWDROPDOWN

    状态

    0

    打开(状态为TRUE)或收起(状态为FALSE)下拉列表

    CB_GETDROPPEDSTATE

    0

    0

    检测列表的当前下拉状态,返回TRUE表示拉下,FALSE表示收起

    当用户在组合框中进行选择操作时,Windows向对话框过程发送WM_COMMAND消息,消息中wParam参数的低16位是组合框ID,高16位是通知码,用来表示用户的操作,通知码的定义如表

    5.6  用户操作组合框后的通知码

    通  知  码

    说    明

    CBN_SELCHANGE

    用户将要选择一个项目(鼠标移动到了这个项目上)

    CBN_CLOSEUP

    下拉列表关闭(可能是选择完成也可能是取消选择)

    CBN_SELENDOK

    用户完成选择项目

    CBN_SELENDCANCEL

    用户取消选择(鼠标移动到了某个项目上,但并没有按下而是点击了其他控件,或按动了Esc键)

    CBN_DBLCLK

    在CBS_SIMPLE的组合框中双击了一个列表项

    CBN_DROPDOWN

    用户打开了下拉框(按动了编辑框边的下拉按钮)

    如果想在用户选择了一个项目后做相应的动作,最好的办法就是处理CBN_SELENDOK通知码,因为这才意味着用户真正完成了一个选择动作

    以上的操作都是针对下拉列表部分的,另外也有很多消息是针对组合框中的编辑控件的,对组合框的窗口句柄发送WM_GETTEXT和WM_SETTEXT,操作的对象就是组合框的编辑控件;如果要限制编辑控件中文本的最大输入长度,可以发送CB_LIMITTEXT消息,这时候wParam参数指定最大数量;当用户在编辑框中编辑文本的时候,Windows在用户输入之后、字符显示之前会发送CBN_EDITUPDATE通知码;当字符在编辑框中显示以后,又会发送CBN_EDITCHANGE通知码。所以在处理WM_COMMAND消息时通过处理这两个通知码可以检测到用户的输入操作。

    组合框是子窗口控件中比较复杂的一种,这里介绍的是常用的消息和通知码,另外还有少量不常用的内容,读者可以自行查看相关的资料。

    8. 使用列表框

     

    5.7  列表框可以使用的风格

     

    风    格

    说    明

    LBS_DISABLENOSCROLL

    在不需滚动的时候也显示垂直滚动条

    LBS_EXTENDEDSEL

    在多选列表框中允许按住Shift键同时选中一个范围

    LBS_MULTIPLESEL

    允许多选,如果不定义的话则是单选列表框

    LBS_NOSEL

    列表框项目只能查看不能选择

    LBS_NOTIFY

    用户点击或双击项目时向父窗口发送WM_COMMAND消息

    LBS_SORT

    自动按字母顺序排序插入的项目

    LBS_USETABSTOPS

    列表框项目的文本中允许将Tab字符的位置展开

    LBS_STANDARD

    组合LBS_NOTIFY,LBS_SORT,WS_VSCROLL和WS_BORDER

     

    一般单选列表框只需定义LBS_STANDARD就可以了。

     

     

     

     

     

     

     

     

     

     

     

  • 相关阅读:
    数据结构(二)(三)栈和队列
    数据结构(一)线性表
    中信卡笔试代码
    Jenkins搭建-简单使用
    python 生成指定两个ip间的所有ip
    形象理解 什么是磁盘碎片
    形象理解软件位宽 32位和64位的区别
    看板娘>_
    Win10一张网卡设置多个ip地址
    VMware ubuntu安装tools灰色?
  • 原文地址:https://www.cnblogs.com/xuankuwa/p/3659356.html
Copyright © 2020-2023  润新知