求高手用VC++6.0做一个很简单的vc列表框应用实例案例发我邮箱

16547人阅读
笔记(32)
打开,【文件】【新建】,弹出下面窗口:选择【工程】【】,填上【工程名称】,选择【位置】,【确定】即可。
点【完成】,如下图:
点【确定】,如下图:
【文件】,【新建】,【】,填好【名称】,【确定】,如下图:
在【】头文件里写:
然后【文件】,【新建】,【资源脚本】(),填上【文件名】,点【确定】。如下图:
【】【】【】选择【】(使用作为静态库)。如下图:
【】【】点【是】,【】,【】
【】【】,【类的类型】选【】,填好【名称】,【】填【】【确定】后再【确定】,如下图:
同理,【】【】,【类的类型】选【】,填好【】,【】选【】,【确定】,如下图:
在【】下双击【】,在下一行写
双击【】,填上头文件写上下面的代码:
#include “GameWnd.h”
BOOLGameApp::InitInstance()
m_pMainWnd=new GameW
m_pMainWnd-&ShowWindow(SW_SHOW);
m_pMainWnd-&UpdateWindow();
returnTRUE;
双击【】,补充完整,并注释掉
双击【】,把改成属性
切换到【】编译运行。
补充画直线和椭圆:
右击【】,选择【】
双击【】,【确定】
写如下代码:
引用文章:
链表实例迷宫
通过创建程序进行第一个窗口菜单程序,在头文件中必须导入,这个是类库的头文件,需要调用类库中的窗口类来创建窗口,所以需要该文件。
创建资源文件,资源文件用来保存声音、图片等外部资源,即使当前的程序中你用不着资源文件,你也要创建它。
步骤:创建文件后,对其选择资源包含,这个选项用来输入资源文件引用的头文件名,由于我们没有资源,所以保持默认不变。
在创建完资源文件后,类向导在下就可以使用了,类向导的作用是建立文件用来存放类的信息,创建的文件是文件。
由于我们这个程序使用了的类和函数,所以我们要设置以下项目,让它们可以调用函数库。
步骤:下的在菜单下的设置。其中有两个选项,以静态链接的方式调用它的作用是你编译后的程序就直接包含了调用的部分的库,文件可能会大些,但是可以直接移到其他机器上运行;还有一个是,它的作用是你编译后的程序中不包含库,所以文件会比较校,但是如果你的程序直接移动到一个没有安装过的机器上时,可能会导致找不到的。此处我们要选择以静态链接的方式调用。当创建完成之后,我们就创建了一个应用程序,这个应用程序可以以静态连接的方式包含,也就是说,这个程序可以包含微软基础库中的内容,比如说函数或者类,这样我们这个程序就可以挪动到其他没有安装过的机器上运行。
是微软提供的一套基础类库,它包装了系统提供的,用于进行系统应用软件开发,可以使开发更简单,也能提高开发效率。指的就是。
我们使用为我们提供的创建类工具来继承编写好的显示窗口的类。下有个,然后打开分别创建一个类和一个普通类,前者的父类选择,后者的父类选择,将前的子文件中的构造放开权限,变成公开的。然后编译修正头文件错误。
由于代表我们当前的应用程序,因此它的生老病死代表着应用程序的生老病死。它要在窗口诞生之前诞生,在窗口灭亡之后灭亡。一句话,它的寿命就是应用程序的寿命。从专业角度上来说,基于框架生成的应用程序必须有且仅有一个从派生的类的对象,在创建窗口之前必须先构造该对象。因此,我们首先要在的派生类中,也就是中定义一个对象,这个对象代表应用程序。方法在文件的构造上方定义即可。
定义初始化函数,在中声明,在构造函数前声明然后在它对应的文件,也就是实现文件中定义该函数。在的构造函数中初始化与在方法中初始化的不同在于会调用函数对应用程序进行初始化,而类似于控制台的函数它不用程序来编写,由类库提供,并在应用程序启动时调用。
在中创建窗口,编写代码,意思是:在堆中创建一个窗口类对象,这个是一个窗口类,并用来指向它,是在中定义的一个窗口类型的指针变量,它指向了应用程序的主框架窗口。由于是的子类,而我们定义的类又是从继承而来,因此中可以调用它的祖父的指针变量。同时,由于这里要调用类的构造函数,所以要在的开头添加类的头文件。最后为添加的构造函数,添加代码迷宫游戏第一个参数是窗口类名,假如为,那么采用窗口类默认提供的类名,第二个参数是窗口的标题。
返回中,在刚定义的窗口指针下调用其方法,如该段代码表示调用函数将创建的窗口显示出来。在调用完函数之后窗口已经建立,但它是在内存中的,并不显示在显示器中,只有调用函数后才会显示出来,它的参数指定窗口如何显示,在第一次调用时,应该使用作为参数,在随后调用函数时候,必须给定一个值,比如说显示、隐藏。
窗口显示以后,假如我们的窗体内容有改变,那么我们还需要更新窗口,使用调用其方法,当窗口有改变的时候,它才起作用。该函数不断发送重绘消息来刷新目标窗体,使窗体产生不断更新的效果,它有一个参数,如果值为,就不对窗口进行更新。最后在这个方法中返回,表示创建完毕。此刻可以编译程序,窗体就会显示在屏幕上。
假设我们要在窗口中显示一个图片,这个图片的文件名为,它是一个位图,要显示这个位图,我们需要与的类打交道。那么什么是类,是的缩写,意思是“图形设备接口”。由于程序员无法直接操作显示卡,所以提供了类,用来做为程序员与显示卡沟通的桥梁,比如说程序员发出画图的命令,那么便会将这个画图的命令翻译成显示卡能懂的语言,然后要求显示卡去做,这样程序员要做的就是如何与建立良好的沟通关系。包含许多绘图类,比如说处理位图的类,处理画刷的类,处理字体的类,处理调色板的类,处理画笔的类以及处理图形设备接口区域的类。
由于我们要显示的是一张位图,所以我们只需用到处理位图的类,其他类就可以暂时放到一边去。
首先创建对象。可以通过左边窗口的窗口右键对应的窗口类,增加成员变量,变量名类型为,而变量名字为,最后访问权限设置为。在类中的构造函数下,通过创建对象。然后通过函数进行读取图片。然后通过方法进行对的赋值,假设函数原型为:各个参数含义如下:
处理包含被装载图像模块的特例。若要装在图像,则设此参数值为。
:处理图像装载。如果参数为而且参数省略。
的值时,那么参数是一个指向保留在模块中装载的图像资源名称,并以为结束符的字符串。如果参数为空,并且被指定,那么这个参数低位字一定是被装载的图像标识的。图像标识符是在头文件中定义的,下面列举出前缀的含义:位图;图标;:光标。如果参数包含值,那么参数是包含有图像的文件名。
指定被装载图像类型。此参数可以为下列值,其含义如下:
装载位图;装载光标;:装载图标。
指定图标或光标的宽度,以像素为单位。如果此参数为并且参数值为,那么函数使用或系统公制值设定宽度;如果此参数为并且值没有被使用,那么函数使用目前的资源宽度。
指定图标或光标的高度,以像素为单位。如果此参数为并且参数值为,那么函数使用或系统公制值设定宽度;如果此参数为并且值没有被使用,那么函数使用目前的资源高度。
根据下面复合值列表指定函数值,值含义如下:
缺省标志,它不作任何事情,它的含义是“无”。
当参数指定为时,使得函数返回一个部分位图,而不是一个兼容的位图。这个标志在装载一个位图,而不是映射它的颜色到显示设备时非常有用。
若或未被设为,使用系统指定的公制值标识光标或图标的宽和高。如果这个参数不被设置且或被设为,函数使用实际资源尺寸。如果资源包含多个图像,则使用第一个图像的大小。
根据参数的值装载图像。若标记未被给定,的值为资源名称。
查找图像的颜色表并且按下面相应的颜色表的灰度进行替换。
若包括和两个值时,则优先。但是,颜色表接口由替代,而不是。
装载黑白图。
若图像将被多次装载则共享。如果未被设置,则再向同一个资源第二次调用这个图像时就会再装载以便这个图像且返回不同的句柄。不要对不同标准尺寸的图像使用装载后可能会有改变,或是从文件中被装载。
句柄是什么?句柄是一个指向指针的指针,我们知道,指针中保存的是内存地址,那么一个指向指针的指针,它保存的就是另一个指针的地址,我们可以通过一个指针来找到另一个指针,然后再通过另一个指针访问到具体的数据。
我们知道,当运行一个占用大量内存的程序时,系统内存很快就会被填满,这时就会自动将那些暂时不用的数据放到硬盘中,而这些数据所占的空间就是虚拟内存。打个比方,电脑的剩余物理内存只有,我们同时运行游戏和,游戏占用内存,而占用,假如没有虚拟内存,那么就不能运行,因为系统无法给分配合适大小的内存,但是有了虚拟内存,那么就可以将游戏的一些不常用的数据转移出来,存放到虚拟内存中,比如说保存到硬盘上的一个叫的文件中,同时释放掉这些被转移的数据,这样就有了足够的内存运行,而当游戏运行到需要加载哪些被转移的数据时,可以释放掉一些不常用的数据,将其保存到硬盘文件中,然后再读取文件中关于游戏的数据,这样循环移动数据的过程就是微软的虚拟内存技术。
我们看到,为了最大限度的使用物理内存,需要经常在武力内存和虚拟内存之间来回移动数据,以此来满足各种应用程序的内存需要。数据被移动意味着它的地址发生了变化。假如我们仍然按照先前的地址来访问它,是会出错的。为了解决这个问题,操作系统专门腾出一块内存空间用来保存数据在内存中的地址变化,操作系统每次移动数据后,都要把数据新的地址告知这个内存空间来保存。而记录地址变化的这块内存空间它的地址是保持不变的。我们把这个不变的地址叫做句柄,我们就可以通过该句柄找到数据的最新地址,然后访问该数据。但是,必须注意的是程序每次重新启动,操作系统所分配的句柄都是不一样的,这就好像每次抽奖都抽到不同的号码一样,当然也有可能抽到同一个号码,不过几率很小。
图片的显示其实是一个复制与粘贴的过程,打个比方:我们将一幅图片复制到中去的时候,通常需要首先确定好操作的图片,然后选择复制,这时图片就自动加载到剪贴板中,通过运行可以看到剪贴板中文件的位置,这个剪贴板可看做是一块内存区域,它保存了复制好的图片,我们完成了加载图片到内存的操作后,接着我们打开,这一步等于是将内存与建立好联系,这样我们就不会粘贴到别的地方去,跟着我们将光标转移到需要粘贴的位置处,最后我们选择粘贴。那么图片就自动粘贴到了中。因此我们要将图片在窗口中显示出来,一共分为四个步骤:第一,将位图复制到内存中;第二,获得作画的区域,即窗口;第三,将内存与窗口相关联;第四,将内存中图片粘贴到窗口中去,完成绘画。
将位图复制到内存中的方法:首先需要在窗口类的构造函数中建立一块内存,通过用指向这块内存,由于这个指针在构造函数结束后还要使用,所以我们最好将指针定义为窗口类的成员,然后去掉构造函数中的声明。
然后我们来获得作画的区域,代表客户区域,客户区域表示用户操作的区域,我们用客户区类声明了一个对象,然后将传递进去,由于是在窗口类的构造函数中定义的,所以指向的是当前窗口类的一个窗口对象。由于指向的是当前的窗口对象,所以就代表这个窗口的客户区域。我们获得了作画的区域以后,接下来就要将内存与绘制图片的窗口相关联,也就是将内存与窗口客户区域相关联,关联的方法使用调用,然后将窗口的地址传递进去,如:这里调用了类的创建兼容成员函数将窗口与内存关联起来。这样就将内存与窗口建立了联系,注意这个函数它需要某个设备环境的内存地址,比如说窗口的内存地址,所以用取地址符取得了窗口的内存地址是的缩写,即设备环境,设备环境好比是画家的画布,而图形位图、画刷、画笔、调色板、字体等则代表画家手中的画笔,选择不同的画笔在不同的画布上作画,则会勾勒出不同的画面。而是设备环境类,集合了多种设备环境,比如说:代表操作窗口的,代表整个屏幕的响应消息的以及响应的。
将图片放到内存中,将中的图片黏贴到窗口中去,,,表示目的地的坐标;,表示目的地的宽度和高度表示内存的;表示图片显示在窗体上是从什么位置开始;表示模式,按原样复制,不拉伸。此时发现运行时什么都没有。现在对增加,左边选择,右边选择,将方法放置到这个位置,再编译运行图像就显示出来了。
什么时候可以调用重画呢当窗体的大小改变或者最小化,窗体需要进行重画。这意味着旧的窗体区域被销毁,新的窗体区域被建立。会捕捉销毁的或者说是无效的窗体区域,并发送两个消息,通知客户区有变化和通知非客户区有变化。非客户区的重画系统自己搞定了,而客户区的重画需要我们自己来完成,它需要响应消息的来重画窗口。在创建函数后会自动创建一行语句:与的区别在于:这个只能用来响应窗口重绘消息,是从派生出来的,在构造时自动调用开始绘图,在函数中获得消息所给予的新的窗口区域的大小,并进行绘制,析构时调用结束绘图,除了清空窗口区域外,还负责从消息队列中清除消息。这样窗体在重画一遍之后就不再重画了。因此,在处理窗口重画时,必须使用,否则消息无法从消息队列中清除,将导致不断地窗口重画。也是从派生出来的,一般用于客户区窗口的绘制,构造时自动调用函数,析构时自动调用函数,由于不能调用从消息队列中清除消息,所以将导致不断的窗口重画。总之,不能像那样在销毁时调用从消息队列中清除消息,所以当销毁后会不断地新建,然后窗体的重画就不停地执行下去。
与的作用:函数的作用是告诉系统,要开始向显示卡中输出图形了,由于系统通常很忙,所以函数把本次请求放到消息队列里。让系统忙完别的事情后来处理这个请求。
但是由于多数电脑的显示卡只有一个,这样要将图形显示完整必须独占显示卡。操作系统很好的处理了这一点,它以线程的方式来处理每个显示请求,比如说:它让一个图形显示完毕后再来显示另一个,而不是一个图形显示一部分,另一个图形也显示一部分。
本章节所要显示的图形是窗口中的人物图片,这样函数就向操作系统发送一个请求,大意是:窗口中的内容需要更新了,你安排好吧。同时它还提供了窗口的句柄以及窗口这个区域的大小。操作系统接受到这个请求,就会为窗口这个区域分配一个句柄,这个句柄表示我们只能在这个窗口区域内绘图,其他区域都是无效的。当函数返回时,就得到了这个句柄,有了这个句柄,接下来的显示都将在这个窗口区域中进行,这个窗口就可以看做是一个画布,我们可以调用一大堆绘画函数在这个画布上涂抹。比如说我们调用函数来显示一幅人物图片。当绘画完成后,我们必须调用函数来释放掉独占的显示卡,因为不释放回去,别的程序永远无法使用被函数霸占的显示卡来显示图形,显示卡就被死锁了。
为增加一个成员二维数组变量,。在窗口的构造函数中如下定义将二维数组变量和图片对象对应起来。
Create(NULL,&迷宫游戏
char ch[8];
for(int i=0;i&4;i++){
for(int j=0;j&2;j++){
&sprintf(ch,&%d_%d.bmp&,i+1,j+1);
bitma [i][j]=new CB&&&&&&&&&&&&&&&&&
mdc = new CDC;
CClientDC dc(this);
mdc-&CreateCompatibleDC(&dc);
mdc-&SelectObject(bitma [0][0]);
然后为窗口类增加,左边选择,进行,增加时间器编号,时间间隔毫秒回调函数此处我们如下操作。在构造函数中我们通过函数,向编译器发送消息,而响应该消息的方法是函数,从而来创建窗口的属性,但不会产生窗口,在窗口显示前进行设置,计时器放在其中表示在窗口启动时进行定义。表示不使用回调函数,通过系统自定义的函数处理消息。在类中定义两个全局变量方向变量,下标图片变量在构造函数中进行赋值,同样右键窗体类中左边选择,,右边选择,在该函数中输入
CClientDC dc(this);
if(dir&=4){
if(index&2){
mdc-&SelectObject(bitma[dir][index]);
index++;
dir++;
mdc-&SelectObject(bitma[dir][index]);
dc.BitBlt(0,0,117,117,mdc,0,0,SRCCOPY);
CFrameWnd::OnTimer(nIDEvent);
以同样方式添加按键事件,下所有代码如下
// TODO: Add your message handler code here and/or call default
CClientDC dc(this);
dc.BitBlt(x,y,117,117,mdc,0,0,WHITENESS);
if(nChar==VK_DOWN){
y+=20;
if(dir==3){
index++;
if(index==2){
if(nChar==VK_LEFT){
if(dir==0){
index++;
if(index==2){
if(nChar==VK_UP){
if(dir==1){
index++;
if(index==2){
if(nChar==VK_RIGHT){
x+=20;
if(dir==2){
index++;
if(index==2){
mdc-&SelectObject(bitma[dir][index]);
dc.BitBlt(x,y,117,117,mdc,0,0,SRCCOPY);
CFrameWnd::OnKeyDown(nChar, nRepCnt, nFlags);
其后将函数和计时器注释掉,编译即可运行。
定义墙壁数组,并记录下入口处的位置:表示可行走,表示墙壁,表示入口,表示出口。
定义墙壁数组
1,1,1,1,1,1,2,1,
3,0,0,1,0,0,0,1,
&1,1,0,0,0,1,1,1,
1,0,0,1,0,0,0,1,
1,1,1,1,0,1,1,1,
1,0,0,0,0,0,0,1,
1,0,1,0,1,0,0,1,
1,1,1,1,1,1,1,1
用来保存入口变量
在构造中增加
for(int j=0;j&8;j++){
if(wall[i][j]==2){
&&&&&&&&&m=i;
wallp =new B
wallp-&m_hObject=LoadImage(NULL,&wall.bmp&,IMAGE_BITMAP,93,100,LR_LOADFORMFILE);
增加成员方法:
,类型名字为。
mdc-&SelectObject(wallp);
for(int i=0;i&8;i++){
for(int j=0;j&8;j++){
if(wall[i][j]==1){
dc.BitBlt(j*93,i*100,117,117,mdc,0,0,SRCCOPY);
mdc-&SelectObject(bitma[0][0]);
dc.BitBlt(n*93,m*100,93,100,mdc,0,0,SRCCOPY);
全局变量中定义
用来判断初始画面是否重画
在计时器的方法中定义:
if(start){
在方法中增加
最后在构造中重新定义窗口大小
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:418248次
积分:6896
积分:6896
排名:第3534名
原创:279篇
转载:17篇
评论:62条
文章:36篇
阅读:8142
阅读:14457
(window.slotbydup = window.slotbydup || []).push({
id: '4740881',
container: s,
size: '200,200',
display: 'inlay-fix'1.新建对话框MFC,在对话框上放一个ListCtrlID:IDC_PATHView:Report2.为ListCtrl添加变量右击-&添加变量m_wndPath3.找到OnInitDialog()函数添加如下代码://&TODO:&在此添加额外的初始化代码m_wndPath.DeleteAllItems();//清空m_wndPath.InsertColumn(0,_T("项目"));//添加列m_wndPath.InsertColumn(1,_T("所在路径"));m_wndPath.SetColumnWidth(0,&150);//设置列宽m_wndPath.SetColumnWidth(1,&350);m_wndPath.SetRedraw(FALSE);//防止重绘int&nI//char|TCHAR项目属性-&字符集:使用多字节字符集TCHAR&Path[MAX_PATH+1];//TCHAR取代char&&MAX_PATH最长路径nIndex=m_wndPath.InsertItem(&0,_T("Windows目录")&);if(&nIndex&&&0&)&return&TRUE;GetWindowsDirectory(Path,MAX_PATH);//取得windows目录m_wndPath.SetItemText(&nIndex,&1,&Path&);LPITEMIDLIST&//桌面CSIDL_DESKTOPDIRECTORY//用来得到系统的某些特定文件夹的位置信息if(SUCCEEDED(SHGetSpecialFolderLocation(NULL,CSIDL_DESKTOPDIRECTORY,&pidl))){&&&&if(SHGetPathFromIDList(pidl,&Path))//功能是把项目标志符列表转换为文档系统路径&&&&{&&&&&&&&nIndex=m_wndPath.InsertItem(&0,_T("桌面"));//成功则返回0&&&&&&&&if(&nIndex&&&0&)&&&&&&&&{&&&&&&&&&&&&return&TRUE;&&&&&&&&}&&&&&&&&m_wndPath.SetItemText(&nIndex,&1,&Path&);&&&&}}m_wndPath.SetRedraw(TRUE);//显示return&TRUE;&&//&除非将焦点设置到控件,否则返回&TRUE4.char被TCHAR取代,若要用则:项目属性-&字符集:使用多字节字符集源码:url:&参考代码:m_wndPath.DeleteAllItems();m_wndPath.InsertColumn(0,"项目");m_wndPath.InsertColumn(1,"所在路径");m_wndPath.SetColumnWidth(0,&150);m_wndPath.SetColumnWidth(1,&350);m_wndPath.SetRedraw(FALSE);int&nIconst&int&nFolder[]={&CSIDL_ALTSTARTUP,CSIDL_APPDATA,CSIDL_BITBUCKET,CSIDL_COMMON_ALTSTARTUP,&&&&CSIDL_COMMON_DESKTOPDIRECTORY,CSIDL_COMMON_FAVORITES,CSIDL_COMMON_PROGRAMS,&&&&CSIDL_COMMON_STARTMENU,CSIDL_COMMON_STARTUP,CSIDL_CONTROLS,CSIDL_COOKIES,&&&&CSIDL_DESKTOP,CSIDL_DESKTOPDIRECTORY,CSIDL_DRIVES,CSIDL_FAVORITES,CSIDL_FONTS,&&&&CSIDL_HISTORY,CSIDL_INTERNET,CSIDL_INTERNET_CACHE,CSIDL_NETHOOD,CSIDL_NETWORK,&&&&CSIDL_PERSONAL,CSIDL_PRINTERS,CSIDL_PRINTHOOD,CSIDL_PROGRAMS,CSIDL_RECENT,&&&&CSIDL_SENDTO,CSIDL_STARTMENU,CSIDL_STARTUP,CSIDL_TEMPLATES&};const&CString&strFolderName[]={&"CSIDL_ALTSTARTUP","CSIDL_APPDATA","回收站","CSIDL_COMMON_ALTSTARTUP",&&&&"CSIDL_COMMON_DESKTOPDIRECTORY","CSIDL_COMMON_FAVORITES","CSIDL_COMMON_PROGRAMS",&&&&"CSIDL_COMMON_STARTMENU","CSIDL_COMMON_STARTUP","控制面板","CSIDL_COOKIES",&&&&"CSIDL_DESKTOP","桌面","我的电脑","收藏夹","字体",&&&&"历史纪录","CSIDL_INTERNET","CSIDL_INTERNET_CACHE","网上邻居","CSIDL_NETWORK",&&&&"我的文档","打印机","CSIDL_PRINTHOOD","程序组","最近打开的文档",&&&&"发送","任务条启动菜单目录","启动目录","临时文档"&};char&Path[MAX_PATH+1];nIndex=m_wndPath.InsertItem(&0,"Windows目录"&);if(&nIndex&&&0&)&return&TRUE;GetWindowsDirectory(Path,MAX_PATH);m_wndPath.SetItemText(&nIndex,&1,&Path&);nIndex=m_wndPath.InsertItem(&0,"System目录"&);if(&nIndex&&&0&)&return&TRUE;GetSystemDirectory(Path,MAX_PATH);m_wndPath.SetItemText(&nIndex,&1,&Path&);int&i,count=sizeof(nFolder)/sizeof(int);for(i=0;i&i++){&&&&LPITEMIDLIST&&&&&LPMALLOC&pShellM&&&&if(SUCCEEDED(SHGetMalloc(&pShellMalloc)))&&&&{&&&&&&&&if(SUCCEEDED(SHGetSpecialFolderLocation(NULL,&&&&&&&&&&&&nFolder[i],&pidl)))&&&&&&&&{&&&&&&&&&&&&if(SHGetPathFromIDList(pidl,&Path))&&&&&&&&&&&&{&&&&&&&&&&&&&&&&nIndex=m_wndPath.InsertItem(&0,strFolderName[i]&);&&&&&&&&&&&&&&&&if(&nIndex&&&0&)&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&pShellMalloc-&Free(pidl);&&&&&&&&&&&&&&&&&&&&pShellMalloc-&Release();&&&&&&&&&&&&&&&&&&&&return&TRUE;&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&m_wndPath.SetItemText(&nIndex,&1,&Path&);&&&&&&&&&&&&}&&&&&&&&&&&&pShellMalloc-&Free(pidl);&&&&&&&&}&&&&&&&&pShellMalloc-&Release();&&&&}}m_wndPath.SetRedraw(TRUE);VC中ListCtrl经验总结先注明一下,这里,我们用m_listctrl来表示一个CListCtrl的类对象,然后这里我们的ListCtrl都是report形式,至于其他的如什么大图标,小图标的暂时不讲,毕竟report是大众话的使用。其次,我们这里用条款一,条款二来描述第一点,第二点,这个是参照《Effective C++》的叫法,俺觉得这么叫比较COOL :)条款一:设置ListCtrl的风格在CSDN上常常看到有人问怎么设置风格的,他们ListCtrl的样子是一个列表,有横条和竖条分界线,然后选中一行,要整一行都选中,而不是只有某一列被选中,等等,这里给一个比较全面的设置方法。//获得原有风格DWORD dwStyle = ::GetWindowLong(m_listctrl.m_hWnd, GWL_STYLE);&dwStyle &= ~(LVS_TYPEMASK);dwStyle &= ~(LVS_EDITLABELS);//设置新风格SetWindowLong(m_listctrl.m_hWnd, GWL_STYLE,dwStyle, |LVS_REPORT | LVS_NOLABELWRAP | LVS_SHOWSELALWAYS);//设置扩展风格DWORD styles = LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES|LVS_EX_CHECKBOXES;ListView_SetExtendedListViewStyleEx(m_listctrl.m_hWnd, styles, styles );其中LVS_EX_FULLROWSELECT 就是前面说得整行选中LVS_EX_GRIDLINES 网格线(只适用与report风格的listctrl)LVS_EX_CHECKBOXES 前面加个checkboxpListCtrl-&SetExtendedStyle( m_listctrl.GetExtendedStyle() | LVS_EX_SUBITEMIMAGES);这也是一个很重要的属性,这样的话,可以在列表中加ICON,记得windows的任务管理器吗,你想做得那样,这个属性也要加哦,这个我以后会讲的~条款二:加入列头这是一个比较实质的东西,给列表框分列,然后加上列头,代码说话,来了TCHAR rgtsz[2][10] = {_T("列头1"), _T("列头2")};LV_COLUMNCRm_listctrl.GetWindowRect(&rect);for(int i=0;i&2;i++){ lvcolumn.mask = LVCF_FMT | LVCF_SUBITEM | LVCF_TEXT | LVCF_WIDTH | LVCF_ORDER; lvcolumn.fmt = LVCFMT_LEFT; lvcolumn.pszText = rgtsz[i]; lvcolumn.iSubItem = lvcolumn.iOrder = if(i==0) {&&&&&&&lvcolumn.cx = rect.Width()*3/5 ;& } else&&&&&&&lvcolumn.cx = rect.Width()*2/5;&&& m_listctrl.InsertColumn(i, &lvcolumn);}这是插入两列的做法,你要插入20列??随便你,依样画葫芦~~lvcolumn.mask 中那个mask可以有各种属性,具体去看msdn吧,条款三:把记录,插入列表框中int nIndex = m_listctrl.GetItemCount();LV_ITEM&& lvitemAdd = {0};lvitemAdd.mask = LVIF_TEXT;lvitemAdd.iItem = nIlvitemAdd.iSubItem = 0;lvitemAdd.pszText =_T("毛毛1");;if (m_listctrl.InsertItem(&lvitemAdd) != -1){&&& LV_ITEM lvitem = {0};&& lvitem.mask = LVIF_TEXT;&& lvitem.iItem = nI&& lvitem.iSubItem = 1;&& lvitem.pszText =_T("毛毛2");&& m_listctrl.SetItem(&lvitem);&&&}nIndex 是当前的行数,然后把新的一行,插在最下面,条款四:给列表中插入图标在report格式中,也能插入图标继续代码说话m_image是个CImageList对象m_image.Create(16,16, TRUE|ILC_COLOR24, 3, 1);m_listctrl.SetImageList(&m_image,LVSIL_SMALL);然后调用CImageList的成员函数int CImageList::Add( HICON hIcon );把ICON插入到imagelist,然后在插入记录的时候lvitemAdd.mask = LVIF_TEXT; lvitemAdd.mask = LVIF_TEXT|LVIF_IMAGE然后添加一个lvitemAdd.iImage =这个n是imagelist中的序号,表示是具体的哪一个图标,list么,呵呵条款五:插入记录时使用额外的信息,lParam 的使用有时候,你想对于某一行,加入一些额外的信息,那么就可以使用这个lParammsdn是这么描述的Specifies the 32-bit value of the item我上次是为了在某一行加入一个信息,窗口句柄,然后是这么加的,int nIndex = m_listctrl.GetItemCount();LV_ITEM&& lvitemAdd = {0};lvitemAdd.mask = LVIF_TEXT|LVIF_IMAGE|LVIF_PARAM;lvitemAdd.iItem = nIlvitemAdd.iSubItem = 0;lvitemAdd.pszText =_T("毛毛1");;lvitemAdd.iImage =lvitemAdd.lParam = (LPARAM)(某个窗口的窗口句柄)if (m_listctrl.InsertItem(&lvitemAdd) != -1){&&& LV_ITEM lvitem = {0};&& lvitem.mask = LVIF_TEXT;&& lvitem.iItem = nI&& lvitem.iSubItem = 1;&& lvitem.pszText =_T("毛毛2");&& m_listctrl.SetItem(&lvitem);&&&}ok,这是一个比较全的例子的,又插ICON,又使用PARAM的条款六 : 点击列表框,获取选中行信息响应NM_CLICK消息,如果你有MSDN,可以看到,有专门关于listview的NM_CLICK的介绍void CMyDlg::OnItemClick(NMHDR* pNMHDR, LRESULT* pResult)&{&&&// TODO: Add your control notification handler code here&&&int nItem = -1;&&&LPNMITEMACTIVATE lpNMItemActivate = (LPNMITEMACTIVATE)pNMHDR;&&&if(lpNMItemActivate != NULL)&& {&&&&&&nItem = lpNMItemActivate-&iI&&&}}现在nItem就是点击选中那行的index了,有了index,获取那行的信息还难吗懒汉说:难,因为你还没讲,晕,那就继续说条款七: 根据行的index,获取该行的信息直接上代码吧LV_ITEM lvitem = {0};lvitem.iItem = nIlvitem.iSubItem = 0;lvitem.mask = LVIF_TEXT|LVIF_IMAGE|LVIF_PARAM;m_listctrl.GetItem(&lvitem)这样,就把nindex,第一列的信息取出来了,包括刚才我们加入的ICON,和那个额外信息(窗口句柄),比如我要获取窗口句柄,就可以hwnd = (HWND)lvitem.lPmask 用来指明你想获取那些信息具体可以查msdn中LVITEM Structure的定义和CListCtrl::GetItem条款八:用程序选中某一行,使之选中选中之 m_listctrl.SetItemState(nIndex,LVIS_SELECTED|LVIS_FOCUSED,LVIS_SELECTED|LVIS_FOCUSED);不选中,取消选中之m_listctrl.SetItemState(nIndex,0,LVIS_SELECTED|LVIS_FOCUSED);条款九:获取当前所有选中的行(多选)这个,俺就比较懒了,抄msdn的代码吧,反正很简单// CListCtrl* pListCtrl = (CListCtrl*) GetDlgItem(IDC_YOURLISTCONTROL);ASSERT(pListCtrl != NULL);POSITION pos = pList-&GetFirstSelectedItemPosition();if (pos == NULL)&& TRACE0("No items were selected!\n");else{&&&while (pos)&&&{&&&&&&int nItem = pList-&GetNextSelectedItem(pos);&&&&&&TRACE1("Item %d was selected!\n", nItem);&&&&& // you could do your own processing on nItem here&&&}}条款十:删除条款九中选中的行这个相对前面九个条款是比较麻烦的,因为如果你要删除多行的话,往往要出错。比如,我现在要删除第0行和第1行(列表的行序列是从0开始的)那么好啊。我来删了m_listctrl.DeleteItem(0)m_listctrl.DeleteItem(1)恭喜你,错了,我好开心啊 :)因为你删除第0行以后,下面的行会往上移,那么原来的第1行就变成了第0行,那么你再 m_listctrl.DeleteItem(1),那么删除的是原来的第2行,真麻烦,所以,只有从下往上删,才是安全的,先删的,不会影响后面的操作,m_listctrl.DeleteItem(1)m_listctrl.DeleteItem(0)但有时候,我们也不知道要删除哪些行,只知道要删除选中的那些行,像条款九中的那些如果我们还是用POSITION pos = m_listctrl.GetFirstSelectedItemPosition();if (pos == NULL)&& TRACE0("No items were selected!\n");else{&&&while (pos)&&&{&&&&&&int nItem = m_listctrl.GetNextSelectedItem(pos);&&&&&&m_listctrl.DeleteItem(nItem );&&&}}你就等着收尸吧这时候我们就要B4微软了,为虾米木有GetLastselectedItemPosition 和GetPrevSelectedItem,多写一对成员函数会死啊 :(没办法,办法自己想,这里有个笨办法POSITION sSelPos = NULL;while(sSelPos = m_listctrl.GetFirstSelectedItemPosition()){&&&int nSelItem = -1;&&&nSelItem = m_listctrl.GetNextSelectedItem(sSelPos);&&&if(nSelItem &= 0 && nSelItem&m_listctrl.GetItemCount())&&&{&&&&&&//好了,这个nSelItem 就是我们要的DD&&&}}GetNextSelectedItem这个函数,看msdn的用法,其实是返回第一个的index,然后走到下一个选中的行去,所以这么做也是安全的,在实际中,俺也是这么做的,测试也通过,没问题的当然,还有个办法,先通过GetFirstSelectedItemPosition和GetNextSelectedItem来获取所有的选中行的index,然后把这些index放到一个数组里,然后再从下往上删唉真麻烦啊,还要不定数组,不说用new在堆上开吧,那么一个vector总是要的吧,麻烦啊,所以我暂时是用上述的办法来删除,也供大家参考,希望能找到更好的办法。VC编程技术点滴(六)使用ListControl控件显示数据表&&
阅读(...) 评论()

我要回帖

更多关于 vc列表框应用实例 的文章

 

随机推荐