首页
归档
友情链接
关于
Search
1
在wsl2中安装archlinux
105 阅读
2
nvim番外之将配置的插件管理器更新为lazy
78 阅读
3
2018总结与2019规划
62 阅读
4
PDF标准详解(五)——图形状态
40 阅读
5
为 MariaDB 配置远程访问权限
33 阅读
软件与环境配置
博客搭建
从0开始配置vim
Vim 从嫌弃到依赖
archlinux
Emacs
MySQL
Git与Github
AndroidStudio
cmake
读书笔记
编程
PDF 标准
从0自制解释器
qt
C/C++语言
Windows 编程
Python
Java
算法与数据结构
PE结构
Thinking
FIRE
菜谱
登录
Search
标签搜索
c++
c
学习笔记
windows
文本操作术
编辑器
NeoVim
Vim
win32
VimScript
emacs
linux
文本编辑器
Java
elisp
反汇编
OLEDB
数据库编程
数据结构
内核编程
Masimaro
累计撰写
314
篇文章
累计收到
31
条评论
首页
栏目
软件与环境配置
博客搭建
从0开始配置vim
Vim 从嫌弃到依赖
archlinux
Emacs
MySQL
Git与Github
AndroidStudio
cmake
读书笔记
编程
PDF 标准
从0自制解释器
qt
C/C++语言
Windows 编程
Python
Java
算法与数据结构
PE结构
Thinking
FIRE
菜谱
页面
归档
友情链接
关于
搜索到
42
篇与
的结果
2015-06-26
windows编程学习笔记(三)ListBox的使用方法
ListBox是Windows中的一种控件,一般被当做子窗口使用,Windows中所有子窗口都是通过发送一个通知码到父窗口父窗口通过WM_COMMAND消息接收,并在此消息中处理,并控制子窗口,ListBox自然也不例外,ListBox中有它独有的消息,通知消息,风格,查看MSDN可以看到风格主要有:LBS_EXTENDEDSEL 用户可以通过SHIFT + 鼠标或者其他组合键进行多选(只能通过SHIFT + 鼠标或者其他组合键)LBS_HASSTRINGS 指定一个自绘的列表框中包含有字符串项,这些字符串的指针由应用程序管理,我们可以利用GetText函数得到相应的字符串LBS_MULTICOLUMN 列表框可以有多列,默认情况是只有一列即一行只有一个字符串,我们可以使用 SetColumnWidth设置列宽LBS_MULTIPLESEL 用户可以同时选择多项(用户单击一项时这项被选中,单击另一项时,这两项都被选中,选择多项时只需要点击不同的项,不需要用组合键的方式,同一项第一次单击时选中,第二次单击时取消选中)LBS_NOINTEGRALHEIGHT 列表框的大小由系统在创建这个列表框的时候决定。一般不会只显示部分列表项LBS_NOREDRAW 列表框的大小在显示后不会改变,但是可以通过发 WM_SETREDRAW消息来取消这一风格LBS_NOTIFY 当用户单击或双击时会发送一条消息到父窗口,风格,父窗口将接收不到用户选择的项LBS_OWNERDRAWFIXED 父窗口负责绘制列表框,这个时候列表框中的项的大小都一样LBS_OWNERDRAWVARIABLE 列表项的大小可以不一样LBS_SORT 字符串会以首字母排序LBS_STANDARD 系统会将字符串排序,同时父窗口会收到用户单机或者双击鼠标的消息LBS_USETABSTOPS 允许用户使用TAB键在各项中切换LBS_WANTKEYBOARDINPUT 当列表框通过键盘获得焦点时会向父窗口发送 WM_VKEYTOITEM 或 WM_CHARTOITEM 消息,以便程序处理特殊的键盘消息LBS_DISABLENOSCROLL 列表框会拥有一个垂直滚动条 ,在列表框不能够显示所有项时显示。一般父窗口通过向列表框发送消息来控制列表框的行为,而发送的消息一般有以下几种:LB_ADDFILE 添加文件LB_ADDSTRING 添加字符串LB_DELETESTRING 删除字符串LB_DIR 添加文件名列表LB_FINDSTRING 返回列表框中的一个字符的索引LB_FINDSTRINGEXACT 在列表框查找第一个与特定字符匹配的字符并返回它的索引LB_GETANCHORINDEX 获取锚点的索引,锚点就是在多选模式下选中的第一项LB_GETCARETINDEX 在多选模式下返回具有焦点条目的索引LB_GETCOUNT 获取列表框中子项的总数LB_GETCURSEL 获取被选中的子项的索引,只在单选模式下有效LB_GETHORIZONTALEXTENT 获取水平滚动条的宽度LB_GETITEMDATA 获取与指定列表项相关的程序的自定义值(长度为32位)LB_GETITEMHEIGHT 获取列表项的高LB_GETITEMRECT 获取列表项边界矩形的大小LB_GETLOCALE 获得当前列表的区域,可以通过该区域决定正确的排序规则或者显示排序后的文本LB_GETSEL 获得列表项的选择状态,被选中时大于0,未被选中时为0,发生错误时小于0LB_GETSELCOUNT 在多选模式下获取当前被选中的项总数LB_GETSELITEMS 在多选模式下,获取选项的值,需要提供一个相应的数组的首地址用来保存返回结果LB_GETTEXT 获取指定项的字符串LB_GETTEXTLEN 获得指定项字符串的长度LB_GETTOPINDEX 获取列表框中显示的第一列的索引,当使用滚动条使显示内容发生变化时,这个索引也会发生改变LB_INITSTORAGE 需要加入大量列表项时使用LB_INSERTSTRING 添加列表项,但是与LB_ADDSTRING不同的是,加入后新字符串不参加排序LB_RESETCONTENT 清除所有列表项LB_SELECTSTRING 从指定位置向后查找我们指定的字符串项,找到后将该项设置为选中状态LB_SELITEMRANGE 在多选模式下,将某一区域内一个或多个项设置为选中状态LB_SETCARETINDEX 在多选模式下,设置给定索引值的矩形设置为焦点矩形,如果该值没有显示,那么滚动条将会自动滚动到相应行LB_SETCOLUMNWIDTH 在多列模式下设置所有项的的列宽,使用这个消息必须保证列表框有LBS_MULTICOLUMN风给LB_SETCOUNT 设置列表项的总数,用于具有LBS_NODATA风给但是不具有LBS_HASSTRINGS风格的列表框LB_SETCURSEL 设置某项处于被选中状态,并将该项加亮显示LB_SETHORIZONTALEXTENT 设置水平滚动条的宽度,当列表框的宽度不足以显示所有项的时候,滚动条出现,否则隐藏LB_SETITEMDATA 设置特定项的值LB_SETITEMHEIGHT 设置列表项的宽。LB_SETLOCALE 设置列表框的当前区域LB_SETSEL 在多选模式下选中某一字符串LB_SETTABSTOPS 设置TAB键停止的位置LB_SETTOPINDEX 设置列表框中的某一项处于可见位置列表框向其父窗口发送的通知码为:LBN_DBLCLK 当某一项被单击时发送LBN_ERRSPACE 当系统不能分配足够的内存来进项相应的处理时发送该通知码LBN_KILLFOCUS 当列表框中某一项失去焦点时发送LBN_SELCANCEL当用户取消选择时发送LBN_SELCHANGE 当用户选择改变时发送LBN_SETFOCUS 当某一项获得焦点时发送下面是一个小例子:(在窗口程序中创建列表框,框中选择人物姓名,可以得到人物的相应信息)利用到的结构体的定义如下:struct PERSON { const char *pszName; int nAge; const char *pszPhoneNum; };首先在WM_CREATE中创建:HWND hList = CreateWindow("LISTBOX", "", WS_CHILD | WS_BORDER | WS_VISIBLE | LBS_HASSTRINGS | LBS_NOTIFY | LBS_NOINTEGRALHEIGHT, 0,0,200,800,hWnd, (HMENU)123, g_hInst, NULL); for(int i = 0; i < 3; i++) { SendMessage(hList, LB_ADDSTRING, 0, (LPARAM)(g_Person[i].pszName)); } SendMessage(hList, LB_SETCURSEL, (WPARAM)0, 0);关于列表框的显示与行为控制都在WM_COMMAND中处理:if (123 == LOWORD(wParam)) { if (LBN_DBLCLK == HIWORD(wParam)) { int nIndex = SendMessage((HWND)lParam, LB_GETCURSEL, 0, 0); sprintf(szBuf, "姓名:%s 年龄:%d 电话:%s", g_Person[nIndex].pszName, g_Person[nIndex].nAge,g_Person[nIndex].pszPhoneNum); InvalidateRect(hWnd, NULL, TRUE); } }当点击某一项后需要在窗口中显示,显示的工作可以在WM_PAINT中完成PAINTSTRUCT ps; RECT rtClient; GetClientRect(hWnd, &rtClient); HDC hDc = BeginPaint(hWnd, &ps); DrawText(hDc, szBuf, strlen(szBuf), &rtClient, DT_CENTER | DT_VCENTER | DT_SINGLELINE); EndPaint(hWnd, &ps);
2015年06月26日
4 阅读
0 评论
0 点赞
2015-06-19
Windows程序设计笔记(二) 关于编写简单窗口程序中的几点疑惑
在编写窗口程序时主要是5个步骤,创建窗口类、注册窗口类、创建窗口、显示窗口、消息环的编写。对于这5个步骤为何要这样写,当初我不是太理解,学习到现在有些问题我基本上已经找到了答案,同时对于Windows对于窗口的管理机制有了更深的认识,下面我通过问答的方式,一一写出自己之前的疑惑。问题一、窗口类与窗口之间有何关系?答:窗口类与窗口就好像C++中类与对象的关系,窗口是窗口类的具体表现,在注册窗口类成功后,系统并没有创建窗口,只是分配的相应的存储空间存储了我们为窗口类填写的一些信息。只有调用CreateWindow后系统才会创建窗口。窗口类中的成员变量定义的是这一类窗口的共性,比如定义窗口类风格为子窗口,那么用这个窗口类创建的窗口就都是子窗口。而创建窗口时传入的参数是具体窗口显示形式,比如大小、长宽等;既然窗口类是窗口的共性,那么窗口过程自然是所有用该类创建的窗口都公用这个窗口过程,窗口过程根据窗口句柄来判断处理那个窗口,而Windows中提供了获取并修改窗口过程的方法(超类化),所以只要掌握了窗口句柄那么就可以控制该类的所有窗口。问题二、为何需要注册窗口类,而不是根据我们填写的窗口类结构体来直接创建?答:在程序中为窗口类定义了一个变量,填写好各个成员变量后,这个只是我们自己知道我们定义了一个新的窗口过程但是系统并不知道我们,系统中有一个专门的表用来存储系统中各个窗口类的信息,注册窗口类实际上是将我们填写的窗口类的信息添加到系统的这个表中,以后创建时系统会在这个表中查找相应的窗口类。问题三、创建窗口时使用的是窗口类名而不是我们定义的窗口类的变量?答:上面说过,系统中有一个专门用于管理各个窗口类的表,在调用CreateWindow函数时会首先在表中查找是否有这个类,没有的话就返回出错,并不会在我们所定义的窗口类结构体变量的内存中查找,通过这一点我们可以知道其实对于所有的窗口类只需要使用一个结构体变量来创建所有的窗口类,只要注册后系统将相关信息存储到窗口类表中,改变这个变量并不会对前面创建的窗口类产生影响。窗口类表中采用类名作为主码(不知道是不是真的采用数据库的相关方法存储,但是系统是根据类名来唯一确定一条窗口类的信息),并不是保存类结构体变量的地址,所以注册后这个窗口类就与这个变量没有关系。问题四、为何需要一个窗口句柄、为何系统不直接利用窗口类生成一个窗口,用窗口类名表示窗口窗口?答:在实际使用中,可能很多窗口具有相同或者相似的性质,因此为了代码的重用,系统抽象出一个窗口类用来管理具有共性的窗口,这样就表示一个窗口类可以产生多个窗口,这样用窗口类的信息管理窗口自然就不现实,而系统采用句柄的方式,而窗口句柄又是什么呢?系统对每个窗口也有一张表,而这个句柄就是相应的表项的一个索引。问题五、在消息环中GetMessage和Dispatchmessage各有什么作用,为什么一个应用程序只需要一个消息环而不是每个窗口一个消息环?答:这就涉及到系统的消息机制,Windows采用的是消息机制,每一个应用程序都有一个消息队列,系统有一个总的消息队列用来存储所有的产生的消息,在我们产生相应的操作时,首先由硬件捕捉到再由驱动程序做简单的翻译,再由系统根据传来的信息,组织生成一个MSG结构体,然后由系统根据MSG 中的第一参数发送到相应应用程序的消息队列中,这个是由PostMessage或者是SendMessage来完成,应用程序会不断的从自己的消息队列中取出消息,这是由GetMessage完成,取出后根据MSG中的HWND参数确定是哪个窗口的消息,从而发送到相依的窗口过程中。每个应用程序只有一个消息环,而取出消息和将消息分配到对应的窗口过程都争对的这一个消息队列自然没有必要写多个消息环问题六、系统是如何根据窗口句柄找到相应的窗口过程的?答:系统中有两个表分别管理窗口类和窗口,窗口类中最重要的信息是窗口类名和窗口过程地址,有了类名就可以在定义窗口时找到类的相关信息,有了窗口过程地址就可以处理消息,毕竟对于程序而言最重要的还是对于信息的处理,窗口什么的都只是用于与用户更好的交互。而系统在处理消息时是如何知道该调用哪个窗口过程的呢,有一种思路是根据消息中的HWND找到窗口表项,根据表项找到相应的窗口类,最后根据窗口类找到对应的窗口过程,但是实际上系统并不是这样做的,当要处理大量的消息时这样查找效率太低,所以系统的做法是在窗口表项中增加一些空间,用来存储从窗口类中拷贝的信息,在创建窗口时系统将窗口过程等重要信息拷贝一份放到相应的窗口信息表项中,在查找时只要找到窗口就可以找到窗口过程,所有在子类化时我们只是修改窗口表中的窗口过程,这样只改变对应窗口的窗口过程,而用该类创建的其他窗口的窗口过程并不受影响,而改变窗口类的窗口过程,则所有用该类创建的窗口的窗口过程都被修改。
2015年06月19日
5 阅读
0 评论
0 点赞
1
...
4
5