﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-农妇，山泉，有点儿田-随笔分类-MFC</title><link>http://www.cppblog.com/deadpunk/category/2138.html</link><description>我没有技术</description><language>zh-cn</language><lastBuildDate>Tue, 03 Mar 2009 18:25:48 GMT</lastBuildDate><pubDate>Tue, 03 Mar 2009 18:25:48 GMT</pubDate><ttl>60</ttl><item><title>转载：VC窗口启动时隐藏</title><link>http://www.cppblog.com/deadpunk/archive/2009/03/03/75377.html</link><dc:creator>活着就是折腾，所以当然要骠悍的折腾</dc:creator><author>活着就是折腾，所以当然要骠悍的折腾</author><pubDate>Tue, 03 Mar 2009 02:06:00 GMT</pubDate><guid>http://www.cppblog.com/deadpunk/archive/2009/03/03/75377.html</guid><wfw:comment>http://www.cppblog.com/deadpunk/comments/75377.html</wfw:comment><comments>http://www.cppblog.com/deadpunk/archive/2009/03/03/75377.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/deadpunk/comments/commentRss/75377.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/deadpunk/services/trackbacks/75377.html</trackback:ping><description><![CDATA[原帖地址：<a href="http://hi.baidu.com/edudo/blog/item/33c898f31428c8cd0b46e0d4.html">http://hi.baidu.com/edudo/blog/item/33c898f31428c8cd0b46e0d4.html</a><br><br>对于这类问题，大家最容易想到的可能就是在PreCreateWindow中添加cs.style &amp;=~WS_VISIBLE;这是不可行的。程序仍可使用ShowWindow()将窗体显示出来.<br>
<p>1.基于对话框的程序<br>&nbsp;&nbsp; 我在论坛上看到有人说在OnInitDialog()中加上ShowWindow(SW_HIDE)对话框便不出现了，其实是不可行的。至于原因，我认为是系统是在OnInitDialog()后调用ShowWindow(SW_SHOW)让对话框显示的.可以添加下面代码:<br>CXXDlg::OnInitDialog()<br>{<br>... <br>Sleep(5000);<br>return TRUE;<br>} <br>可以发现5秒后对话框才显示出来.至于在何时调用的我也不清楚，但是我们可以在OnPaint()中加上ShowWindow(SW_HIDE),来达到隐藏的目的.不过使用的这种方法，会有一点闪烁.另外一种方法就是在OnInitDialog()中使用SetWindowPlacement()</p>
<br>
<p>GetWindowPlacement(&amp;m_wp); //恢复时用<br>ModifyStyleEx(WS_EX_APPWINDOW,WS_EX_TOOLWINDOW);//从任务栏中去掉.</p>
<br>
<p>WINDOWPLACEMENT wp;<br>wp.length=sizeof(WINDOWPLACEMENT);<br>wp.flags=WPF_RESTORETOMAXIMIZED;<br>wp.showCmd=SW_HIDE;<br>SetWindowPlacement(&amp;wp);</p>
<br>
<p>还有一种更简单的方法:在OnInitDialog()中调用下面代码.<br>SetWindowPos(&amp;wndTop,0,0,0,0,NULL);</p>
<br>
<p>2.基于单文档的程序</p>
<br>
<p>我们一般采用的方法就是将InitInstance()中的:<br>CXXApp::InitInstance()<br>{<br>&nbsp;&nbsp; //m_pMainWnd-&gt;ShowWindow(SW_SHOW);<br>}<br>但是这样窗体还会有闪烁。<br>因为MFC还要在ActiveFrame显示框架，所以我们还需要添加下面代码:<br>void CMainFrame::ActivateFrame(int nCmdShow) <br>{<br>&nbsp;&nbsp; nCmdShow=SW_HIDE;<br>&nbsp;&nbsp; CFrameWnd::ActivateFrame(nCmdShow);<br>}<br>或者:<br>int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)<br>{<br>&nbsp;&nbsp; AfxGetApp()-&gt;m_nCmdShow=SW_HIDE;<br>}<br>顺便说一下，上面通过ModifyStyleEx(WS_EX_APPWINDOW,WS_EX_TOOLWINDOW)的方法来实现从任务栏去掉按钮，这样当显示时还要切换显示的模式，其实还可以通过调用TaskbarList组件直接删除和添加:<br>ITaskbarList的定义在shobjidl.h(vs.net)中。<br>也可以手动定义:<br>DECLARE_INTERFACE_(ITaskbarList,IUnknown)<br>{<br>&nbsp;&nbsp; STDMETHOD(QueryInterface)(THIS_ REFIID riid,LPVOID* ppvObj) PURE;<br>&nbsp;&nbsp; STDMETHOD_(ULONG,AddRef)(THIS) PURE;<br>&nbsp;&nbsp; STDMETHOD_(ULONG,Release)(THIS) PURE;<br>&nbsp;&nbsp; STDMETHOD(ActivateTab)(HWND) PURE;<br>&nbsp;&nbsp; STDMETHOD(AddTab)(HWND) PURE;<br>&nbsp;&nbsp; STDMETHOD(DeleteTab)(HWND) PURE;<br>&nbsp;&nbsp; STDMETHOD(HrInit)(void) PURE;<br>};<br>BOOL CMy2App::InitInstance()<br>{ <br>&nbsp;&nbsp; CoInitialize(0);<br>&nbsp;&nbsp; ITaskbarList *pObj;<br>&nbsp;&nbsp; CoCreateInstance(CLSID_TaskbarList,NULL,CLSCTX_INPROC_SERVER,IID_ITaskbarList,(void**)&amp;pObj);<br>&nbsp;&nbsp; pObj-&gt;DeleteTab(m_pMainWnd-&gt;m_hWnd); //从任务栏上删除<br>&nbsp;&nbsp; //pObj-&gt;AddTab(m_pMainWnd-&gt;m_hWnd); //添加</p>
<br>
<p>&nbsp;&nbsp; pObj-&gt;Release();<br>&nbsp;&nbsp; CoUninitialize();<br>}</p>
<br>
<p>所以我们还可以用将窗体最小化,并从任备栏上删除按钮的方法来实现隐藏.</p>
<p>&#160;</p>
<p>有很多应用程序要求一起动就隐藏起来，这些程序多作为后台程序运行，希望不影响其他窗口，往往只在托盘区显示一个图标。这些程序通常都是对话框程序，而对话框在初始化的过程上与SDI、MDI的初始化是不同的，对话框只需要DoModule或者是CreateDialog等等对话框函数调用一次便可，SDI、MDI则要好几步才行。这样看来，对话框在使用方法上面是隐藏了不少细节的，其中就没有SDI、MDI所要求的ShowWindow(nCmdShow)这一步。因此对话框要想一运行就隐藏，并不是很直接的。有一些方法可以做到这一点，下面我们就来看看几种方案。 <br><br>1．定时器 <br>最直观，又是最无奈的一个方法就是使用定时器。既然我们在对话框开始显示之前不能用ShowWindow(SW_HIDE)将其隐藏，那就给一个时间让它显示，完了我们在隐藏它。 <br><br>方法： <br><br>1.在OnInitDialog()函数里设置定时器：（WINDOWS API里面响应消息WM_INITDIALOG） <br><br>SetTimer(1, 1, NULL); <br><br>2.添加处理WM_TIMER的消息处理函数OnTimer,添加代码： <br><br>if(nIDEvent == 1) <br><br>{ <br><br>DeleteTimer(1); <br><br>ShowWindow(SW_HIDE); <br><br>} <br><br>这种方法的缺点是显而易见的，使用定时器，使得程序的稳定性似乎打一个折扣；窗口是要先显示出来的，那么效果就是窗口闪了一下消失。 <br><br>2．改变对话框显示状况 <br>在对话框初始化时改变其显示属性可以让它隐藏起来。方法是调用SetWindowPlacement函数： <br><br><br>BOOL CDialogExDlg::OnInitDialog() <br><br>{ <br><br>CDialog::OnInitDialog(); <br><br>//DO something <br><br><br>WINDOWPLACEMENT wp; <br><br>wp.length=sizeof(WINDOWPLACEMENT); <br><br>wp.flags=WPF_RESTORETOMAXIMIZED; <br><br>wp.showCmd=SW_HIDE; <br><br>SetWindowPlacement(&amp;wp); <br><br>return TRUE; <br><br>} <br><br><br><br>在需要显示时（通常是响应热键或者托盘图标的鼠标消息）： <br><br><br>WINDOWPLACEMENT wp; <br><br>wp.length=sizeof(WINDOWPLACEMENT); <br><br>wp.flags=WPF_RESTORETOMAXIMIZED; <br><br>wp.showCmd=SW_SHOW; <br><br>SetWindowPlacement(&amp;wp); <br><br><br>这样的效果很不理想：窗口显示在屏幕的左上角，并且是只有标题栏，要正常显示，还需加上如下代码： <br><br>定义一个成员变量CRect rect; <br><br>在OnInitDialog()里面： <br><br>GetWindowRect(&amp;rect); <br><br>在需要显示的地方： <br><br>SetWindowPos(&amp;wndNoTopMost, wndRc.left, wndRc.top, wndRc.right, wndRc.bottom, SWP_SHOWWINDOW); <br><br>CenterWindow(); <br><br>即使这样，效果还是很差。 <br><br>这种方法还有一个弊端是当程序开始运行并且隐藏起来后，原来激活的窗口变成了非激活状态了，而当对话框显示出来后，对话框自身也是非激活状态的。 <br><br><br>3．不绘制窗口 <br>当对话框显示时将要响应消息WM_PAINT绘制客户区，相应消息WM_NCPAINT绘制窗口边框。我们在窗口第一次自绘自身时隐藏窗口，可以收到比较良好的效果。由于窗口是先画窗口边框，所以我们仅需处理WM_NCPAINT即可。代码如下： <br><br>添加WM_NCPAINT处理函数。 <br><br>void CMyDialog::OnNcPaint() <br><br>{ <br><br>static int i = 2; <br><br>if(i &gt; 0) <br><br>{ <br><br>i --; <br><br>ShowWindow(SW_HIDE); <br><br>} <br><br>else <br><br>CDialog::OnNcPaint(); <br><br>} <br><br>这里有个问题：为什么要定义静态变量i而且设其值为2呢？ <br><br>我们只要窗口隐藏第一次，所以定义这个变量可以判断是否时首次显示窗口。当程序开始运行时，系统发送（SendMessage）WM_NCPAINT消息，此时程序的窗口边框应该被显示，但是此时我们没有作任何显示的操作，而是将窗口隐藏，ShowWindow(SW_HIDE)将把窗口的WS_VISIBLE属性去掉，继续执行，程序将检查WS_VISIBLE属性，如果没有则显示窗口，所以又发送了一个WM_NCPAINT消息。所以我们要处理两次WM_NCPAINT消息。 <br><br>在需要窗口显示时，调用ShowWindow(SW_SHOW)即可。 <br><br>程序执行的结果是，原来处于激活状态的窗口可能会闪动两下，然后仍然处于激活状态。这种处理方式比上面的方式要优越得多。 <br><br><br>4．将对话框作为子窗口 <br>这种方法是采用SDI框架，主窗口始终隐藏，对话框作为主窗口的成员变量，在CMainFrame::OnCreate()里面加入下代码： <br><br>if(!dlg.Create(IDD_MYDIALOG, this)) <br><br>{ <br><br>return &#8211;1; <br><br>} <br><br>dlg.ShowWindow(SW_HIDE); <br><br>在要显示对话框的地方用dlg.ShowWindow(SW_SHOW);即可。注意，主窗口一定要隐藏，否则对话框可能会闪现一下。 <br><br>隐藏状态栏窗口 <br>上面介绍了几种检查对话框的方法，大家如果试过的话可能已经注意到系统状态栏里在程序启动时会有程序的图标闪过，在隐藏对话框的时候这个也是要隐藏的，方法很简单： <br><br>在OnInitDialog()函数里面加上ModifyStyleEx(WS_EX_APPWINDOW, WS_EX_TOOLWINDOW);即可。在要显示窗口的地方加上代码ModifyStyleEx(WS_EX_TOOLWINDOW, WS_EX_APPWINDOW);即将窗口的扩展样式改回来。 <br><br></p>
<img src ="http://www.cppblog.com/deadpunk/aggbug/75377.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/deadpunk/" target="_blank">活着就是折腾，所以当然要骠悍的折腾</a> 2009-03-03 10:06 <a href="http://www.cppblog.com/deadpunk/archive/2009/03/03/75377.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>VC制作屏幕保护程序</title><link>http://www.cppblog.com/deadpunk/archive/2007/11/22/37117.html</link><dc:creator>活着就是折腾，所以当然要骠悍的折腾</dc:creator><author>活着就是折腾，所以当然要骠悍的折腾</author><pubDate>Thu, 22 Nov 2007 02:04:00 GMT</pubDate><guid>http://www.cppblog.com/deadpunk/archive/2007/11/22/37117.html</guid><wfw:comment>http://www.cppblog.com/deadpunk/comments/37117.html</wfw:comment><comments>http://www.cppblog.com/deadpunk/archive/2007/11/22/37117.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/deadpunk/comments/commentRss/37117.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/deadpunk/services/trackbacks/37117.html</trackback:ping><description><![CDATA[<strong><font style="BACKGROUND-COLOR: #ffff66">VC</font></strong>5.0/6.0是开发<strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">屏幕保护</strong>程序的好工具。静态链接库SCRNSAVE.LIB对<strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">屏幕保护</strong>程序提供了支持。SCRNSAVE.LIB包含了建立<strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">屏幕保护</strong>程序的主程序和缺省功能，用户可以方便地使用SDK进行编程并与之连接。尽管SDK编程相对MFC麻烦，但编写相对简单的<strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">屏幕保护</strong>程序却相当容易甚至比用MFC编程更简单。 <br>　　也可以使用MFC编写<strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">屏幕保护</strong>程序。但遗憾的是MFC不支持SCRNSAVE.LIB，必须手工完成原来由SCRNSAVE.LIB提供的功能，比较麻烦和不好理解。不过，编写复杂的<strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">屏幕保护</strong>程序时，MFC对于显示模块和对话框处理可以提供比SDK方便得多的功能。为简单起见先介绍如何使用SDK编写<strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">屏幕保护</strong>程序。 <br><br><br>一. <strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">屏幕保护</strong>程序和SCRNSAVE.LIB <br><br>　　先从开发者的角度对<strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">屏幕保护</strong>程序说明如下： <br>　　首先，<strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">屏幕保护</strong>程序是Win32 API 支持一种特殊的应用程序并由系统自动激活。其机制是当条件满足时，系统向当前活动窗口发出字参数 wParam 值为SC_SCREENSAVE 的WM_SYSCOMMAND消息，然后由当前活动窗口执行SYSTEM.INI文件中[boot]区指定的<strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">屏幕保护</strong>程序。 <br><br>　　<strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">屏幕保护</strong>程序激活的条件是 <br>　　1. 在规定时间内没有鼠标或键盘输入. <br>　　2. 当前的活动窗口是标准的WINDOWS应用程序。因为非WINDOWS应用，不会理睬WM_SYSCOMMAND消息。 <br>　　3. 显然，如果当前活动的程序接管了字参数 wParam 值为SC_SCREENSAVE 的WM_SYSCOMMAND 消息并且不传递到 DefWindowProc函数就可以禁止<strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">屏幕保护</strong>程序。这对某些运行中不愿意被打断的程序如视频播放，光盘刻录程序特别有用。 <br><br>　　其次，可以在控制面板的显示器中选择需要的<strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">屏幕保护</strong>程序，并可以配置<strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">屏幕保护</strong>程序的参数。<strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">屏幕保护</strong>程序应该提供配置<strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">屏幕保护</strong>程序的对话框。 <br><br>　　再次,<strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">屏幕保护</strong>程序有特别的输出函数，资源定义和变量声明。SCRNSAVE.LIB包含了建立<strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">屏幕保护</strong>程序的主程序。<strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">屏幕保护</strong>程序启动时SCRNSAVE.LIB自动创建一全屏窗口，并描述窗口类为无光标的满黑屏。 <br>　　用户编写的<strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">屏幕保护</strong>程序必须包含三个基本函数ScreenSaverProc，ScreenSaverConfigureDialog 和RegisterDialogClasses 并与SCRNSAVE.LIB连接。 <br>　　1．ScreenSaverProc 窗口函数处理特定的消息并把未处理的消息传递给SCRNSAVE.LIB 。ScreenSaverProc 一般处理以下消息： <br>　　WM_CREATE 读取.INI或注册表的初始化数据，设置定时器以及其他初始化操作。 <br>　　WM_ERASEBKGND 擦除背景为下一步绘图作准备。 <br>　　WM_TIMER 进行绘图输出。用户可以实现自己的动画功能以及其他操作。 <br>　　WM_DESTROY 删除定时器以及其他对象 <br>　　ScreenSaverProc 把未处理的消息传递到SCRNSAVE.LIB中的 DefScreenSaverProc函数 处理。由它完成许多复杂和关键的操作比如何时激活，何时关闭等，大大方便了<strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">屏幕保护</strong>程序的编写。 <br>　　2．ScreenSaverConfigureDialog函数处理<strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">屏幕保护</strong>程序配置对话框。该对话框由控制面板的显示器设置程序调用。用户输入的配置数据输出到.INI或注册表中。 <br>　　3. RegisterDialogClasses函数登记<strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">屏幕保护</strong>程序配置对话框的窗口类。如果不使用特殊的窗口或控件，可以简单地返回TRUE。 <br><br>　　另外，编写<strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">屏幕保护</strong>程序还有一些原则。 <br>　　1. 为使控制面板能够识别，<strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">屏幕保护</strong>程序的扩展名必须改为.SCR并存放在WINDOWS目录下。 <br>　　2. <strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">屏幕保护</strong>程序的图标（ICON）在资源文件中必须定义为ID_APP。ID_APP由系统的SCRNSAVE.H.定义。 <br>　　3. 资源文件中必须包含一描述字符串。该字符串用于控制面板显示<strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">屏幕保护</strong>程序的名字。它必须位于字符串表的首位。SCRNSAVE.H.定义其ID为1。 <br>　　4. 资源文件中<strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">屏幕保护</strong>程序配置对话框的ID必须为DLG_SCRNSAVECONFIGURE。它由系统的SCRNSAVE.H.定义。 <br><br><br>二.编程实例 <br><br>　　1.最小的<strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">屏幕保护</strong>程序MiniSaver。这是一个仅包含最基本模块的<strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">屏幕保护</strong>程序，运行时在屏幕上显示一行活动的文字。步骤如下: <br>　　第一步，在<strong style="COLOR: black; BACKGROUND-COLOR: #ffff66">VC</strong>5.0/6.0中建立32位应用工程(不选MFC WIZARD EXE).建立如下的MiniSaver.CPP文件： <br>#include <br>#include<br>// SCRNSAVE.LIB的头文件<br>#include "resource.h"<br>//声明三个基本的函数<br>LRESULT WINAPI ScreenSaveProc<br>(HWND,UINT,WPARAM,LPARAM);<br>BOOL WINAPI ScreenSaveConfigureDialog<br>(HWND,UINT,WPARAM,LPARAM);<br>BOOL WINAPI RegisterDialogClasses(HINSTANCE);<br>//定义三个基本的函数<br>LRESULT WINAPI ScreenSaverProc<br>(HWND hWnd, UINT message, WPARAM wParam,<br>LPARAM lParam)<br>{ HDC hDC;<br>RECT rc;<br>static int xpos;//文本的横坐标<br>static char SlideText[]="欢迎使用<strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">屏幕保护</strong>程序!";<br>static UINT timerID;//定时器<br>switch (message)<br>{<br>case WM_CREATE:<br>xpos=0;<br>timerID=SetTimer(hWnd,1,250,NULL);//设置定时器<br>break;<br><br>case WM_ERASEBKGND:<br>//空操作，交由DefScreenSaverProc处理<br>break;<br>case WM_TIMER:<br>hDC=GetDC(hWnd);<br>//清屏<br>SetRect(&amp;rc,0,0,GetSystemMetrics(SM_CXSCREEN),<br>GetSystemMetrics(SM_CYSCREEN))<br>FillRect(hDC,&amp;rc,GetStockObject(BLACK_BRUSH));<br>//输出文本<br>SetTextColor(hDC,RGB(255*rand(),<br>255*rand(),255*rand()));<br>SetBkColor(hDC,RGB(0,0,0));<br>TextOut(hDC,xpos,GetSystemMetrics(SM_CYSCREEN)/2,<br>SlideText,strlen(SlideText));<br>//移动文本的横坐标<br>xpos=(xpos+10)%GetSystemMetrics(SM_CXSCREEN);<br>ReleaseDC(hWnd,hDC);<br>break;<br><br>case WM_DESTROY:<br>KillTimer(hWnd,timerID);//删除定时器<br>PostQuitMessage (0);<br>return 0;<br>}<br>return DefScreenSaverProc<br>(hWnd,message,wParam,lParam);<br>}<br><br>BOOL WINAPI ScreenSaverConfigureDialog<br>(HWND hWnd,UINT message,WPARAM wParam,<br>LPARAM lParam)<br>{//暂时不需要配置对话框，仅返回FALSE<br>return FALSE;<br>}<br><br>BOOL WINAPI RegisterDialogClasses<br>(HINSTANCE hInstance)<br>{//一般不需要，仅返回TRUE <br>return TRUE;<br>}<br><br><br>　　第二步，定义资源文件MiniSaver.rc。在<strong style="COLOR: black; BACKGROUND-COLOR: #ffff66">VC</strong>环境下生成一图标，其ID为ID_APP。向字符串表加入ID为IDS_DESCRIPTION字符串"MiniSaver"，并作为字符串表第一项 <br>　　第三步，编译连接并将生成的MiniSaver.EXE更名为MiniSaver.SCR拷入WINDOWS目录。注意, 编译前一定要在Project菜单的Setting中的Link选项中加上SCRNSAVE.LIB库。 <br>　　第四步，控制面板的显示器设置中选择<strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">屏幕保护</strong>程序MiniSaver就可以使用了。注意不要急于配置<strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">屏幕保护</strong>程序，因为MiniSaver还有没提供配置对话框。 <br><br>　　2.较完整的<strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">屏幕保护</strong>程序MySaver。该<strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">屏幕保护</strong>程序提供了配置对话框和关于对话框，并且使用了图象显示。读者可以将自己喜爱的图象加到资源中。 <br>　　第一步，在<strong style="COLOR: black; BACKGROUND-COLOR: #ffff66">VC</strong>5.0/6.0中建立32位应用工程(不选MFC WIZARD EXE)并定义资源文件MiniSaver.rc。 <br>　　　　在<strong style="COLOR: black; BACKGROUND-COLOR: #ffff66">VC</strong>环境下生成一图标，其ID为ID_APP。 <br>　　　　向字符串表加入ID为IDS_DESCRIPTION字符串"MiniSaver"，并作为字符串表第一项。加入ID为idsAPPName<br>　　　　字符串"Screen Saver.MySaver"，说明见后面程序。 <br>　　　　加入ID为IDB_BITMAP1的位图 <br>　　　　加入ID为DLG_ABOUT对话框。仅有一ID为IDOK的按钮 <br>　　　　加入ID为ID_APP。此对话的ID由SCRNSAVE.H定义且只能为DLG_SCRNSAVECONFIGURE。其中有ID为IDC_EDIT<br>　　　　的EDIT控件，ID为IDOK，IDCANCEL和IDABOUT的按钮。 <br>　　　　值得注意的是RESOURCE.H定义的ID_APP和DLG_SCRNSAVECONFIGURE可能与SCRNSAVE.H预定义的值冲突，可<br>　　　　手动地将RESOURCE.H中的ID_APP设为100，DLG_SCRNSAVECONFIGURE设为2003即可。 <br>　　第二步，建立如下的MySaver.CPP文件： <br>#include #include <br><br>#include "resource.h"<br>//声明三个基本的函数<br>LRESULT WINAPI ScreenSaveProc<br>(HWND,UINT,WPARAM,LPARAM);<br>BOOL WINAPI ScreenSaveConfigureDialog<br>(HWND,UINT,WPARAM,LPARAM);<br>BOOL WINAPI RegisterDialogClasses(HINSTANCE);<br>BOOL WINAPI AboutDialog(HWND,UINT,WPARAM,LPARAM);<br>//定义全局变量<br>char szIniFileName[]="control.ini";<br>//<strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">屏幕保护</strong>程序配置数据存放在control.ini文件<br>char szSection[32];<br>//<strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">屏幕保护</strong>程序配置数据在control.ini文件位置区名称<br>char szEntry[]="Slide Text:";<br>//<strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">屏幕保护</strong>程序配置数据项名称<br>char SlideText[256];<br>//<strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">屏幕保护</strong>程序配置数据，这里是文本内容<br>//定义三个基本的函数<br>LRESULT WINAPI ScreenSaverProc<br>(HWND hWnd,UINT message, WPARAM wParam,<br>LPARAM lParam)<br>{ static HBITMAP hBmp;//位图句柄<br>HDC hDC,hMemDC;//hMemDC是内存设备，缓存位图。<br>RECT rc;<br>static int xpos=0;<br>static UINT timerID;<br>switch (message)<br>{<br>case WM_CREATE:<br>//文件位置区名称szSection赋值为资源<br>idsAPPName。其中hMainInstance为//SCRNSAVE.LIB<br>定义的<strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">屏幕保护</strong>程序实例句柄<br>LoadString(hMainInstance,idsAPPName,<br>szSection,sizeof(szSection));<br>strcpy(SlideText,"欢迎使用<strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">屏幕保护</strong>程序!");<br>//读control.ini文件中[Screen Saver.MySaver]<br>区的配置数据到SlideText<br>GetPrivateProfileString(szSection,szEntry, <br>SlideText,SlideText,<br>sizeof(SlideText),szIniFileName); <br>//取位图<br>hBmp=LoadBitmap(hMainInstance,<br>MAKEINTRESOURCE(IDB_BITMAP1));<br>timerID=SetTimer(hWnd,1,250,NULL);<br>break;<br><br>case WM_ERASEBKGND:<br>hDC=GetDC(hWnd);<br>//显示位图<br>hMemDC=CreateCompatibleDC(hDC);<br>SelectObject(hMemDC,hBmp);<br>SetRect(&amp;rc,0,0,GetSystemMetrics(SM_CXSCREEN),<br>GetSystemMetrics(SM_CYSCREEN)-25);<br>BitBlt(hDC,rc.top,rc.left,rc.right,rc.bottom,<br>hMemDC,rc.top,rc.left,SRCCOPY);<br>//清除底行，为文本显示作准备。<br>SetRect(&amp;rc,0,GetSystemMetrics(SM_CYSCREEN)-25<br>GetSystemMetrics(SM_CXSCREEN)，<br>GetSystemMetrics(SM_CYSCREEN));<br>FillRect(hDC,&amp;rc,GetStockObject(BLACK_BRUSH));<br>ReleaseDC(hWnd,hDC);<br>DeleteDC(hMemDC);<br>return 1;<br><br>case WM_TIMER:<br>hDC=GetDC(hWnd);<br>//清除底行<br>SetRect(&amp;rc,0,GetSystemMetrics(SM_CYSCREEN)-25,<br>GetSystemMetrics(SM_CXSCREEN),<br>GetSystemMetrics(SM_CYSCREEN));<br>FillRect(hDC,&amp;rc,GetStockObject(BLACK_BRUSH));<br>//输出文本<br>SetTextColor(hDC,RGB(255*rand(),<br>255*rand(),255*rand()));<br>SetBkColor(hDC,RGB(0,0,0));<br>TextOut(hDC,xpos,GetSystemMetrics(SM_CYSCREEN)-25,<br>SlideText,strlen(SlideText));<br>xpos=(xpos+10)%GetSystemMetrics(SM_CXSCREEN);<br>ReleaseDC(hWnd,hDC);<br>break;<br><br>case WM_DESTROY:<br>DeleteObject(hBmp);<br>KillTimer(hWnd,timerID);<br>PostQuitMessage (0);<br>return 0;<br>}<br>return DefScreenSaverProc<br>(hWnd,message,wParam,lParam);<br>}<br><br>BOOL WINAPI ScreenSaverConfigureDialog<br>(HWND hWnd,UINT message,WPARAM wParam,<br>LPARAM lParam)<br>{ switch (message)<br>{<br>case WM_INITDIALOG:<br>LoadString(hMainInstance,idsAPPName,<br>szSection,sizeof(szSection));<br>strcpy(SlideText,"欢迎使用<strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">屏幕保护</strong>程序!");<br>GetPrivateProfileString(szSection,<br>szEntry,SlideText,<br>SlideText,sizeof(SlideText),szIniFileName); <br>SetDlgItemText(hWnd,IDC_EDIT,SlideText);<br>SetFocus(GetDlgItem(hWnd,IDC_EDIT));<br>return FALSE;<br><br>case WM_COMMAND:<br>switch(wParam)<br>{<br>case IDOK:<br>//取EDIT控件文本数据并写入control.ini文件<br>GetDlgItemText(hWnd,IDC_EDIT,<br>SlideText,sizeof(SlideText));<br>WritePrivateProfileString(szSection,<br>szEntry,SlideText,szIniFileName);<br>EndDialog(hWnd,TRUE);<br>return TRUE;<br><br>case IDCANCEL:<br>EndDialog(hWnd,FALSE);<br>return TRUE;<br><br>case IDABOUT:<br>//调用ABOUT对话框<br>DialogBox(hMainInstance, <br>MAKEINTRESOURCE(DLG_ABOUT),<br>hWnd,(FARPROC)AboutDialog);<br>return TRUE;<br>}<br>break;<br>}<br>return FALSE;<br>}<br><br>BOOL WINAPI RegisterDialogClasses<br>(HINSTANCE hInstance)<br>{<br>return TRUE;<br>}<br><br>BOOL WINAPI AboutDialog<br>(HWND hWnd,UINT message,WPARAM wParam,<br>LPARAM lParam)<br>{ <br>switch (message)<br>{<br>case WM_INITDIALOG:<br>return TRUE;<br><br>case WM_COMMAND:<br>switch(wParam)<br>{<br>case IDOK:<br>EndDialog(hWnd,TRUE);<br>return TRUE;<br>}<br>break;<br>}<br>return FALSE;<br>}<br><br>　　 最后，编译连接并将生成的MiniSaver.EXE更名为MiniSaver.SCR拷入WINDOWS目录。此时可以使用配置对话框了。<br>
<img src ="http://www.cppblog.com/deadpunk/aggbug/37117.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/deadpunk/" target="_blank">活着就是折腾，所以当然要骠悍的折腾</a> 2007-11-22 10:04 <a href="http://www.cppblog.com/deadpunk/archive/2007/11/22/37117.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Check Box控件和程序在关闭是报内存错误</title><link>http://www.cppblog.com/deadpunk/archive/2007/04/05/21327.html</link><dc:creator>活着就是折腾，所以当然要骠悍的折腾</dc:creator><author>活着就是折腾，所以当然要骠悍的折腾</author><pubDate>Thu, 05 Apr 2007 08:28:00 GMT</pubDate><guid>http://www.cppblog.com/deadpunk/archive/2007/04/05/21327.html</guid><wfw:comment>http://www.cppblog.com/deadpunk/comments/21327.html</wfw:comment><comments>http://www.cppblog.com/deadpunk/archive/2007/04/05/21327.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/deadpunk/comments/commentRss/21327.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/deadpunk/services/trackbacks/21327.html</trackback:ping><description><![CDATA[<p>今天给根据别人改的方法重新修改了Alarm Store Simulator，加了一个check box，直接用(CButton*)GetDlgItem(IDC_CHECKBOXXX)->GetCheck();获得当前checkbox的状态，当然还能用SetCheck()更改，可是当关闭对话框的时候竟然报xxxxxx memory can not be read xxxxxxx的错误，单步进去发现死在dialog的析构函数上了，结果给这个从CDialog中继承的对话框加了一个空的析构函数，然后问题解决，可以成功关闭对话框，现在还没弄懂，这个问题有待进一步分析。。。</p>

知道要用空析构函数的原因了： 如果给一个从Cdialog中继承的窗口类添加了WM_SIZE消息响应函数，则一定要定义窗口的析构函数，否则会报错，哪怕是空的析构函数也可以避免错误。

另外，AfxGetMainWnd()->UpdateData(TRUE);不能随便用，滥用的结果是程序会出windows常规错误窗口，提示abort or retry or cancel, 会死在里面dodataex中，也可能是由于多线程的原因，还没弄清楚，反正要慎重，一般的控件用setwindowstext就可以显示新的控件内容了。



 <img src ="http://www.cppblog.com/deadpunk/aggbug/21327.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/deadpunk/" target="_blank">活着就是折腾，所以当然要骠悍的折腾</a> 2007-04-05 16:28 <a href="http://www.cppblog.com/deadpunk/archive/2007/04/05/21327.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]回调函数指南（Callback Functions Tutorial）</title><link>http://www.cppblog.com/deadpunk/archive/2007/03/27/20673.html</link><dc:creator>活着就是折腾，所以当然要骠悍的折腾</dc:creator><author>活着就是折腾，所以当然要骠悍的折腾</author><pubDate>Tue, 27 Mar 2007 01:33:00 GMT</pubDate><guid>http://www.cppblog.com/deadpunk/archive/2007/03/27/20673.html</guid><wfw:comment>http://www.cppblog.com/deadpunk/comments/20673.html</wfw:comment><comments>http://www.cppblog.com/deadpunk/archive/2007/03/27/20673.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/deadpunk/comments/commentRss/20673.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/deadpunk/services/trackbacks/20673.html</trackback:ping><description><![CDATA[
		<div class="postText">
				<font face="Verdana">
						<i>Author:Marius Bancila<br />http://www.codeguru.com/Cpp/Cpp/cpp_mfc/callbacks/article.php/c10557/<br />翻译by：AllenTing<br />环境：C/C++/VC++</i>
						<br />
						<br />介绍：<br />　　如果你正在读这篇文章，你很可能想知道什么是回调(callback)函数。这篇文章揭示了什么是回调函数，回调函数的好处，为什么你要使用它等等。尽管如此，在学习什么是回调函数前，你必须对函数指针熟悉。如果不是这样，请参考c/c++书籍或者下列链接：<br /><br />　　The Syntax of C and C++ Function Pointers<br />　　http://www.newty.de/fpt/fpt.html<br />　　Pointers to member functions<br />　　http://www.parashift.com/c++-faq-lite/pointers-to-members.html<br />　　Declaring, Assigning, and Using Function Pointers<br />　　http://www.eskimo.com/~scs/cclass/int/sx10a.html<br /> <br /><b>什么是回调函数？</b><br /><br />　　简单的说，回调函数是一个通过函数指针调用的函数。对于一个传递给其它函数的参数，如果你传递的是一个函数的指针(地址)，当这个指针被用来调用它所指向的函数时，就被称为构造了一个回调函数。<br /><br /><b>为什么我们要使用回调函数？</b><br /><br />　　调用者并不关心被调用者是谁；它所知道的是具有特定原型的被调用者以及一些可能的限制（比如，返回值可以是整数，不过特定的值有特定含义）   <br /><br />　　如果你想知道实践中回调函数多有用，想象一下你想写一个排序算法实现的库（的确很经典），比如冒泡排序，希尔排序，shake排序，快速排序等等。关注点在于为了是你的库更加通用，你不想嵌入排序逻辑（一个数组内两个元素之间哪一个在前）到你的函数中。你想让客户决定哪一种逻辑。或者说，你想让库对各种数据类型都有用（int,floats,strings 等等）。因此，你应该怎样做？你会使用函数指针并且利用回调。   <br /><br />　　回调被用于通告。举个例子，你需要在你的应用中设置一个计时器。一旦计时器过期，你的应用程序要被告知。然而，计时器机理的实现者并不知道你的应用程序。实际上，只要一个指向给定原型的函数的指针，并且通过使用该指针，构造一个回调来通知你的应用（计时）事件发生既可。的确，SetTimer() WinAPI就是使用回调函数来通知计时器已经过期的。（假如没有提供回调函数，会发送一个消息给应用程序的队列）<br /><br />　　另一个使用回调原理并且来自WinAPI函数的例子是EnumWindow()，用于枚举屏幕上所有顶级窗口。<br /><br />　　EnumWindow()通过调用应用程序为每个窗口（通过传递窗口的句柄）提供的函数，迭代顶级窗口。<br /><br />　　如果被调用方返回一个值，迭代继续；否则迭代停止。EnumWindow()并不关心被调用方在哪儿以及对传递的句柄做了些什么。它只关心返回值，因为基于返回值它会决定迭代是否继续。<br /><br />　　不过，回调函数继承与C。所以，在C++中回调函数应该只能用于接口C代码和已存在的回调接口。除了这些情况外，应该使用虚方法或者函数，而不是回调函数。<br /><br /><b>一个简单的实现例子</b><br /><br />　　现在参照这个在附件中能找到的例子。我已经创建了一个叫做sort.dll的动态链接库。它用来导出一个将是你的回调函数类型，称为CompareFunction的类型：<br /><br /><div style="BORDER-RIGHT: rgb(204,204,204) 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: rgb(204,204,204) 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: rgb(204,204,204) 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: rgb(204,204,204) 1px solid; BACKGROUND-COLOR: rgb(238,238,238)"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><font face="Courier New"><span style="COLOR: rgb(0,0,0)">typedef </span><span style="COLOR: rgb(0,0,255)">int</span><span style="COLOR: rgb(0,0,0)"> (__stdcall </span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)">CompareFunction)(</span><span style="COLOR: rgb(0,0,255)">const</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">byte</span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)">, </span><span style="COLOR: rgb(0,0,255)">const</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">byte</span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)">);</span></font></div><br />　　它也导出两个叫做Bubblesort() 和Quicksort()的方法，通过按照名字实现相应排序算法，他们都具有相同的原型但提供了不同的行为。<br /><br /><div style="BORDER-RIGHT: rgb(204,204,204) 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: rgb(204,204,204) 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: rgb(204,204,204) 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: rgb(204,204,204) 1px solid; BACKGROUND-COLOR: rgb(238,238,238)"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><font face="Courier New"><span style="COLOR: rgb(0,0,255)">void</span><span style="COLOR: rgb(0,0,0)"> DLLDIR __stdcall Bubblesort(</span><span style="COLOR: rgb(0,0,255)">byte</span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)"> array,<br />                                 </span><span style="COLOR: rgb(0,0,255)">int</span><span style="COLOR: rgb(0,0,0)"> size,<br />                                 </span><span style="COLOR: rgb(0,0,255)">int</span><span style="COLOR: rgb(0,0,0)"> elem_size,<br />                                 CompareFunction cmpFunc);</span></font></div><br /><div style="BORDER-RIGHT: rgb(204,204,204) 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: rgb(204,204,204) 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: rgb(204,204,204) 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: rgb(204,204,204) 1px solid; BACKGROUND-COLOR: rgb(238,238,238)"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><font face="Courier New"><span style="COLOR: rgb(0,0,255)">void</span><span style="COLOR: rgb(0,0,0)"> DLLDIR __stdcall Quicksort(</span><span style="COLOR: rgb(0,0,255)">byte</span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)"> array,<br />                                </span><span style="COLOR: rgb(0,0,255)">int</span><span style="COLOR: rgb(0,0,0)"> size,<br />                                </span><span style="COLOR: rgb(0,0,255)">int</span><span style="COLOR: rgb(0,0,0)"> elem_size,<br />                                CompareFunction cmpFunc);</span></font></div><br />　　这两个函数有以下参数：<br /><br />　　byte* array： 一个指向数组元素的指针（并不关心什么类型）<br />　　int size：数组中元素的个数<br />　　int elem_size： 数组元素的大小（字节为单位）<br />　　CompareFunction cmpFunc：具有上述原型的回调函数的指针。<br /><br />　　这两个函数的实现进行了数组的排序。然而，一旦需要决定两个元素中的哪一个在前，回调就需要用来指向那个地址作为参数的函数。对于库的编写者，并不关心这两个函数在哪儿实现，以及如何实现。它所关注的是两个元素（即待比较的两个元素）的地址以及返回下列值中的一个（这就是库的开发者和客户的对比）<br /><br />　　-1：如果第一个元素较小并且/或应该在第二个元素之前（在有序数组中）<br />　　0：如果两个元素相等并且/或他们的相对位置无关紧要（有序数组中每个元素都可以排在另一个之前）<br />　　1：如果第一个元素较大并且/或应该在第二个元素之后。（有序数组中）<br /><br />　　就像明确描述的对比那样，Bubblesort()的实现是这样的：（Quicksort()更复杂些，详见附件）<br /><br /><div style="BORDER-RIGHT: rgb(204,204,204) 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: rgb(204,204,204) 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: rgb(204,204,204) 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: rgb(204,204,204) 1px solid; BACKGROUND-COLOR: rgb(238,238,238)"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><font face="Courier New"><span style="COLOR: rgb(0,0,255)">void</span><span style="COLOR: rgb(0,0,0)"> DLLDIR __stdcall Bubblesort(</span><span style="COLOR: rgb(0,0,255)">byte</span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)"> array,<br />                                 </span><span style="COLOR: rgb(0,0,255)">int</span><span style="COLOR: rgb(0,0,0)"> size,<br />                                 </span><span style="COLOR: rgb(0,0,255)">int</span><span style="COLOR: rgb(0,0,0)"> elem_size,<br />                                 CompareFunction cmpFunc)<br />{<br />   </span><span style="COLOR: rgb(0,0,255)">for</span><span style="COLOR: rgb(0,0,0)">(</span><span style="COLOR: rgb(0,0,255)">int</span><span style="COLOR: rgb(0,0,0)"> i</span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)">0</span><span style="COLOR: rgb(0,0,0)">; i </span><span style="COLOR: rgb(0,0,0)">&lt;</span><span style="COLOR: rgb(0,0,0)"> size; i</span><span style="COLOR: rgb(0,0,0)">++</span><span style="COLOR: rgb(0,0,0)">)<br />   {<br />      </span><span style="COLOR: rgb(0,0,255)">for</span><span style="COLOR: rgb(0,0,0)">(</span><span style="COLOR: rgb(0,0,255)">int</span><span style="COLOR: rgb(0,0,0)"> j</span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)">0</span><span style="COLOR: rgb(0,0,0)">; j </span><span style="COLOR: rgb(0,0,0)">&lt;</span><span style="COLOR: rgb(0,0,0)"> size</span><span style="COLOR: rgb(0,0,0)">-</span><span style="COLOR: rgb(0,0,0)">1</span><span style="COLOR: rgb(0,0,0)">; j</span><span style="COLOR: rgb(0,0,0)">++</span><span style="COLOR: rgb(0,0,0)">)<br />      {<br />         </span><span style="COLOR: rgb(0,128,0)">//</span><span style="COLOR: rgb(0,128,0)"> make the callback to the comparison function</span><span style="COLOR: rgb(0,128,0)"><br /></span><span style="COLOR: rgb(0,0,0)">         </span><span style="COLOR: rgb(0,0,255)">if</span><span style="COLOR: rgb(0,0,0)">(</span><span style="COLOR: rgb(0,0,0)">1</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,0)">==</span><span style="COLOR: rgb(0,0,0)"> (</span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)">cmpFunc)(array</span><span style="COLOR: rgb(0,0,0)">+</span><span style="COLOR: rgb(0,0,0)">j</span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)">elem_size,<br />                  array</span><span style="COLOR: rgb(0,0,0)">+</span><span style="COLOR: rgb(0,0,0)">(j</span><span style="COLOR: rgb(0,0,0)">+</span><span style="COLOR: rgb(0,0,0)">1</span><span style="COLOR: rgb(0,0,0)">)</span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)">elem_size))<br />         {<br />            </span><span style="COLOR: rgb(0,128,0)">//</span><span style="COLOR: rgb(0,128,0)"> the two compared elements must be interchanged</span><span style="COLOR: rgb(0,128,0)"><br /></span><span style="COLOR: rgb(0,0,0)">            </span><span style="COLOR: rgb(0,0,255)">byte</span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)"> temp </span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">new</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">byte</span><span style="COLOR: rgb(0,0,0)">[elem_size];<br />            memcpy(temp, array</span><span style="COLOR: rgb(0,0,0)">+</span><span style="COLOR: rgb(0,0,0)">j</span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)">elem_size, elem_size);<br />            memcpy(array</span><span style="COLOR: rgb(0,0,0)">+</span><span style="COLOR: rgb(0,0,0)">j</span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)">elem_size,<br />                   array</span><span style="COLOR: rgb(0,0,0)">+</span><span style="COLOR: rgb(0,0,0)">(j</span><span style="COLOR: rgb(0,0,0)">+</span><span style="COLOR: rgb(0,0,0)">1</span><span style="COLOR: rgb(0,0,0)">)</span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)">elem_size,<br />                   elem_size);<br />            memcpy(array</span><span style="COLOR: rgb(0,0,0)">+</span><span style="COLOR: rgb(0,0,0)">(j</span><span style="COLOR: rgb(0,0,0)">+</span><span style="COLOR: rgb(0,0,0)">1</span><span style="COLOR: rgb(0,0,0)">)</span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)">elem_size, temp, elem_size);<br />            delete [] temp;<br />         }<br />      }<br />   }<br />}</span></font></div><br />　　在客户着一边，必须要有一个地址作为Bubblesort()函数参数的回调函数。由于是简单例子，我写了一个比较两个整数和字符串的函数：<br /><br /><div style="BORDER-RIGHT: rgb(204,204,204) 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: rgb(204,204,204) 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: rgb(204,204,204) 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: rgb(204,204,204) 1px solid; BACKGROUND-COLOR: rgb(238,238,238)"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><font face="Courier New"><span style="COLOR: rgb(0,0,255)">int</span><span style="COLOR: rgb(0,0,0)"> __stdcall CompareInts(</span><span style="COLOR: rgb(0,0,255)">const</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">byte</span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)"> velem1, </span><span style="COLOR: rgb(0,0,255)">const</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">byte</span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)"> velem2)<br />{<br />   </span><span style="COLOR: rgb(0,0,255)">int</span><span style="COLOR: rgb(0,0,0)"> elem1 </span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)">(</span><span style="COLOR: rgb(0,0,255)">int</span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)">)velem1;<br />   </span><span style="COLOR: rgb(0,0,255)">int</span><span style="COLOR: rgb(0,0,0)"> elem2 </span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)">(</span><span style="COLOR: rgb(0,0,255)">int</span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)">)velem2;<br />   </span><span style="COLOR: rgb(0,0,255)">if</span><span style="COLOR: rgb(0,0,0)">(elem1 </span><span style="COLOR: rgb(0,0,0)">&lt;</span><span style="COLOR: rgb(0,0,0)"> elem2)<br />      </span><span style="COLOR: rgb(0,0,255)">return</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,0)">-</span><span style="COLOR: rgb(0,0,0)">1</span><span style="COLOR: rgb(0,0,0)">;<br />   </span><span style="COLOR: rgb(0,0,255)">if</span><span style="COLOR: rgb(0,0,0)">(elem1 </span><span style="COLOR: rgb(0,0,0)">&gt;</span><span style="COLOR: rgb(0,0,0)"> elem2)<br />      </span><span style="COLOR: rgb(0,0,255)">return</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,0)">1</span><span style="COLOR: rgb(0,0,0)">;<br />   </span><span style="COLOR: rgb(0,0,255)">return</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,0)">0</span><span style="COLOR: rgb(0,0,0)">;<br />}  <br /></span><span style="COLOR: rgb(0,0,255)">int</span><span style="COLOR: rgb(0,0,0)"> __stdcall CompareStrings(</span><span style="COLOR: rgb(0,0,255)">const</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">byte</span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)"> velem1, </span><span style="COLOR: rgb(0,0,255)">const</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">byte</span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)"> velem2)<br />{<br />   </span><span style="COLOR: rgb(0,0,255)">const</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">char</span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)"> elem1 </span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)"> (</span><span style="COLOR: rgb(0,0,255)">char</span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)">)velem1;<br />   </span><span style="COLOR: rgb(0,0,255)">const</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">char</span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)"> elem2 </span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)"> (</span><span style="COLOR: rgb(0,0,255)">char</span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)">)velem2;<br />   </span><span style="COLOR: rgb(0,0,255)">return</span><span style="COLOR: rgb(0,0,0)"> strcmp(elem1, elem2);<br />}</span></font></div><br />　　为了应用到测试中，我写了个小程序。它传递一个具有5个元素的数组和指向回调函数的指针给Bubblesort() 或 Quicksort()：<br /><br /><div style="BORDER-RIGHT: rgb(204,204,204) 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: rgb(204,204,204) 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: rgb(204,204,204) 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: rgb(204,204,204) 1px solid; BACKGROUND-COLOR: rgb(238,238,238)"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><font face="Courier New"><span style="COLOR: rgb(0,0,255)">int</span><span style="COLOR: rgb(0,0,0)"> main(</span><span style="COLOR: rgb(0,0,255)">int</span><span style="COLOR: rgb(0,0,0)"> argc, </span><span style="COLOR: rgb(0,0,255)">char</span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)"> argv[])<br />{<br />   </span><span style="COLOR: rgb(0,0,255)">int</span><span style="COLOR: rgb(0,0,0)"> i;<br />   </span><span style="COLOR: rgb(0,0,255)">int</span><span style="COLOR: rgb(0,0,0)"> array[] </span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)"> {</span><span style="COLOR: rgb(0,0,0)">5432</span><span style="COLOR: rgb(0,0,0)">, </span><span style="COLOR: rgb(0,0,0)">4321</span><span style="COLOR: rgb(0,0,0)">, </span><span style="COLOR: rgb(0,0,0)">3210</span><span style="COLOR: rgb(0,0,0)">, </span><span style="COLOR: rgb(0,0,0)">2109</span><span style="COLOR: rgb(0,0,0)">, </span><span style="COLOR: rgb(0,0,0)">1098</span><span style="COLOR: rgb(0,0,0)">};<br />   cout </span><span style="COLOR: rgb(0,0,0)">&lt;&lt;</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">Before sorting ints with Bubblesort\n</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">;<br />   </span><span style="COLOR: rgb(0,0,255)">for</span><span style="COLOR: rgb(0,0,0)">(i</span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)">0</span><span style="COLOR: rgb(0,0,0)">; i </span><span style="COLOR: rgb(0,0,0)">&lt;</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,0)">5</span><span style="COLOR: rgb(0,0,0)">; i</span><span style="COLOR: rgb(0,0,0)">++</span><span style="COLOR: rgb(0,0,0)">)<br />      cout </span><span style="COLOR: rgb(0,0,0)">&lt;&lt;</span><span style="COLOR: rgb(0,0,0)"> array[i] </span><span style="COLOR: rgb(0,0,0)">&lt;&lt;</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,0)">'</span><span style="COLOR: rgb(0,0,0)">\n</span><span style="COLOR: rgb(0,0,0)">'</span><span style="COLOR: rgb(0,0,0)">;<br />   Bubblesort((</span><span style="COLOR: rgb(0,0,255)">byte</span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)">)array, </span><span style="COLOR: rgb(0,0,0)">5</span><span style="COLOR: rgb(0,0,0)">, </span><span style="COLOR: rgb(0,0,255)">sizeof</span><span style="COLOR: rgb(0,0,0)">(array[</span><span style="COLOR: rgb(0,0,0)">0</span><span style="COLOR: rgb(0,0,0)">]), </span><span style="COLOR: rgb(0,0,0)">&amp;</span><span style="COLOR: rgb(0,0,0)">CompareInts);<br />   cout </span><span style="COLOR: rgb(0,0,0)">&lt;&lt;</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">After the sorting\n</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">;<br />   </span><span style="COLOR: rgb(0,0,255)">for</span><span style="COLOR: rgb(0,0,0)">(i</span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)">0</span><span style="COLOR: rgb(0,0,0)">; i </span><span style="COLOR: rgb(0,0,0)">&lt;</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,0)">5</span><span style="COLOR: rgb(0,0,0)">; i</span><span style="COLOR: rgb(0,0,0)">++</span><span style="COLOR: rgb(0,0,0)">)<br />      cout </span><span style="COLOR: rgb(0,0,0)">&lt;&lt;</span><span style="COLOR: rgb(0,0,0)"> array[i] </span><span style="COLOR: rgb(0,0,0)">&lt;&lt;</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,0)">'</span><span style="COLOR: rgb(0,0,0)">\n</span><span style="COLOR: rgb(0,0,0)">'</span><span style="COLOR: rgb(0,0,0)">;<br />   </span><span style="COLOR: rgb(0,0,255)">const</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">char</span><span style="COLOR: rgb(0,0,0)"> str[</span><span style="COLOR: rgb(0,0,0)">5</span><span style="COLOR: rgb(0,0,0)">][</span><span style="COLOR: rgb(0,0,0)">10</span><span style="COLOR: rgb(0,0,0)">] </span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)"> {</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">estella</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">,<br />                            </span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">danielle</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">,<br />                            </span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">crissy</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">,<br />                            </span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">bo</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">,<br />                            </span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">angie</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">};<br />   cout </span><span style="COLOR: rgb(0,0,0)">&lt;&lt;</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">Before sorting strings with Quicksort\n</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">;<br />   </span><span style="COLOR: rgb(0,0,255)">for</span><span style="COLOR: rgb(0,0,0)">(i</span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)">0</span><span style="COLOR: rgb(0,0,0)">; i </span><span style="COLOR: rgb(0,0,0)">&lt;</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,0)">5</span><span style="COLOR: rgb(0,0,0)">; i</span><span style="COLOR: rgb(0,0,0)">++</span><span style="COLOR: rgb(0,0,0)">)<br />      cout </span><span style="COLOR: rgb(0,0,0)">&lt;&lt;</span><span style="COLOR: rgb(0,0,0)"> str[i] </span><span style="COLOR: rgb(0,0,0)">&lt;&lt;</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,0)">'</span><span style="COLOR: rgb(0,0,0)">\n</span><span style="COLOR: rgb(0,0,0)">'</span><span style="COLOR: rgb(0,0,0)">;<br />   Quicksort((</span><span style="COLOR: rgb(0,0,255)">byte</span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)">)str, </span><span style="COLOR: rgb(0,0,0)">5</span><span style="COLOR: rgb(0,0,0)">, </span><span style="COLOR: rgb(0,0,0)">10</span><span style="COLOR: rgb(0,0,0)">, </span><span style="COLOR: rgb(0,0,0)">&amp;</span><span style="COLOR: rgb(0,0,0)">CompareStrings);<br />   cout </span><span style="COLOR: rgb(0,0,0)">&lt;&lt;</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">After the sorting\n</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">;<br />   </span><span style="COLOR: rgb(0,0,255)">for</span><span style="COLOR: rgb(0,0,0)">(i</span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)">0</span><span style="COLOR: rgb(0,0,0)">; i </span><span style="COLOR: rgb(0,0,0)">&lt;</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,0)">5</span><span style="COLOR: rgb(0,0,0)">; i</span><span style="COLOR: rgb(0,0,0)">++</span><span style="COLOR: rgb(0,0,0)">)<br />      cout </span><span style="COLOR: rgb(0,0,0)">&lt;&lt;</span><span style="COLOR: rgb(0,0,0)"> str[i] </span><span style="COLOR: rgb(0,0,0)">&lt;&lt;</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,0)">'</span><span style="COLOR: rgb(0,0,0)">\n</span><span style="COLOR: rgb(0,0,0)">'</span><span style="COLOR: rgb(0,0,0)">;<br />   </span><span style="COLOR: rgb(0,0,255)">return</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,0)">0</span><span style="COLOR: rgb(0,0,0)">;<br />}</span></font></div><br />　　如果我决定想让排序变为降序排序（最大的在前面），我所要做的是改变回调函数的代码，或者提供另外一个希望的实现。<br />调用习惯：<br /><br />　　在上面的代码中，你可以看到在函数原型中的单词__stdcall。由于它始于双精度，当然是一个编译器相关的扩展，更确切的说是微软相关的版本。任何一个支持基于Win32的应用开发的编译器必须支持这点。一个标有__stdcall的函数使用所谓的标准调用习惯，因为所有 Win32API函数（出去极个别支持可变参数的函数）都使用它。遵循标准调用习惯的函数在返回他们的值给调用方前从堆栈中移除参数。这是Pascal的标准习惯。不过，在C/C++中，调用习惯是调用方清理堆栈而不是被调用方。为了加强使用c/c++调用习惯的函数的行为，__cdecl是必须的。可变参数的函数使用c/c++的调用习惯。<br />   <br />　　windows采用标准调用习惯（即Pascal的习惯）是因为它减少了代码的大小。在早期的windows（运行在640K的内存）这是很重要的。<br />　　如果你不喜欢__stdcall ， 你可以使用CALLBACK的宏， 它定义在windef.h中，<br /><br /><div style="BORDER-RIGHT: rgb(204,204,204) 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: rgb(204,204,204) 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: rgb(204,204,204) 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: rgb(204,204,204) 1px solid; BACKGROUND-COLOR: rgb(238,238,238)"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><font face="Courier New"><span style="COLOR: rgb(0,0,255)">#define</span><span style="COLOR: rgb(0,0,0)"> CALLBACK    __stdcall</span><span style="COLOR: rgb(0,0,0)"><br />or<br /></span><span style="COLOR: rgb(0,0,255)">#define</span><span style="COLOR: rgb(0,0,0)"> CALLBACK    PASCAL</span></font></div><br />　　PASCAL定义为__stdcall<br />这儿有更多关于调用习惯的参考：<br /><br />Calling Convetions in Microsoft Visual C++<br />www.hackcraft.net/cpp/MSCallingConventions/<br /><br />作为回调函数的C++方法<br /><br />由于你很有可能用C++写代码，你想让你的回调函数是一个类的方法。不过，如果你这样写：<br /><font face="Courier New"><br /></font><div style="BORDER-RIGHT: rgb(204,204,204) 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: rgb(204,204,204) 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: rgb(204,204,204) 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: rgb(204,204,204) 1px solid; BACKGROUND-COLOR: rgb(238,238,238)"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><font face="Courier New"><span style="COLOR: rgb(0,0,255)">class</span><span style="COLOR: rgb(0,0,0)"> CCallbackTester<br />{<br /></span><span style="COLOR: rgb(0,0,255)">public</span><span style="COLOR: rgb(0,0,0)">:<br />   </span><span style="COLOR: rgb(0,0,255)">int</span><span style="COLOR: rgb(0,0,0)"> CALLBACK CompareInts(</span><span style="COLOR: rgb(0,0,255)">const</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">byte</span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)"> velem1, </span><span style="COLOR: rgb(0,0,255)">const</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">byte</span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)"> velem2);<br />};<br />Bubblesort((</span><span style="COLOR: rgb(0,0,255)">byte</span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)">)array, </span><span style="COLOR: rgb(0,0,0)">5</span><span style="COLOR: rgb(0,0,0)">, </span><span style="COLOR: rgb(0,0,255)">sizeof</span><span style="COLOR: rgb(0,0,0)">(array[</span><span style="COLOR: rgb(0,0,0)">0</span><span style="COLOR: rgb(0,0,0)">]),<br />           </span><span style="COLOR: rgb(0,0,0)">&amp;</span><span style="COLOR: rgb(0,0,0)">CCallbackTester::CompareInts);</span></font></div><br />用MS编译器，会得到这个编译错误：<br /><br /><i>error C2664: 'Bubblesort' : cannot convert parameter 4 from 'int (__stdcall CCallbackTester::*)(const unsigned char *,const unsigned char *)' to 'int (__stdcall *)(const unsigned char *,const unsigned char *)' There is no context in which this conversion is possible<br /><br /></i>这个错误是因为非静态成员函数额外的参数，即this指针。<br /><br />这就强制你使成员函数变为静态的。如果这不可接受，你可以使用好几种技术克服它。用下列链接来学习：<br /><br />How to Implement Callbacks in C and C++<br />www.newty.de/fpt/callback.html<br /></font>
		</div>
<img src ="http://www.cppblog.com/deadpunk/aggbug/20673.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/deadpunk/" target="_blank">活着就是折腾，所以当然要骠悍的折腾</a> 2007-03-27 09:33 <a href="http://www.cppblog.com/deadpunk/archive/2007/03/27/20673.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]CString 操作指南 </title><link>http://www.cppblog.com/deadpunk/archive/2007/03/27/20672.html</link><dc:creator>活着就是折腾，所以当然要骠悍的折腾</dc:creator><author>活着就是折腾，所以当然要骠悍的折腾</author><pubDate>Tue, 27 Mar 2007 01:27:00 GMT</pubDate><guid>http://www.cppblog.com/deadpunk/archive/2007/03/27/20672.html</guid><wfw:comment>http://www.cppblog.com/deadpunk/comments/20672.html</wfw:comment><comments>http://www.cppblog.com/deadpunk/archive/2007/03/27/20672.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/deadpunk/comments/commentRss/20672.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/deadpunk/services/trackbacks/20672.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 原著：Joseph M. Newcomer翻译：littleloach　　原文出处：codeproject：CString Management						　　通过阅读本文你可以学习如何有效地使用 CString。　　CString 是一种很有用的数据类型。它们很大程度上简化了MFC中的许多操作，使得MFC在做字符串操作的时候方便了很多。不管怎样，使用CString有很多特殊的技巧，特别是对于...&nbsp;&nbsp;<a href='http://www.cppblog.com/deadpunk/archive/2007/03/27/20672.html'>阅读全文</a><img src ="http://www.cppblog.com/deadpunk/aggbug/20672.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/deadpunk/" target="_blank">活着就是折腾，所以当然要骠悍的折腾</a> 2007-03-27 09:27 <a href="http://www.cppblog.com/deadpunk/archive/2007/03/27/20672.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]Visual C++ MFC 中常用宏的含义 </title><link>http://www.cppblog.com/deadpunk/archive/2007/03/27/20670.html</link><dc:creator>活着就是折腾，所以当然要骠悍的折腾</dc:creator><author>活着就是折腾，所以当然要骠悍的折腾</author><pubDate>Tue, 27 Mar 2007 01:25:00 GMT</pubDate><guid>http://www.cppblog.com/deadpunk/archive/2007/03/27/20670.html</guid><wfw:comment>http://www.cppblog.com/deadpunk/comments/20670.html</wfw:comment><comments>http://www.cppblog.com/deadpunk/archive/2007/03/27/20670.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/deadpunk/comments/commentRss/20670.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/deadpunk/services/trackbacks/20670.html</trackback:ping><description><![CDATA[
		<div class="postText">
				<b>AND_CATCHAND_CATCH<br />AND_CATCH(exception_class,exception _object_point_name)</b>
				<br />
				<u>
						<i>说明：</i>
				</u>
				<br />　　定义一个代码块，它用于获取废除当前TRY块中的附加异常类型。使用CATCH宏以获得一个异常类型，然后使用AND_CATCH宏获得随后的异常处理代码可以访问异常对象（若合适的话)已得到关于异常的特别原因的更多消息。在AND_CATCH块中调用THROW_LAST宏以便把处理过程移到下个外部异常框架。AND_CATCH可标记CATCH或AND_CATCH块的末尾。<br /><u><i>注释：</i></u><br />　　AND_CATCH块被定义成为一个C++作用域（由花括号来描述）。若用户在此作用域定义变量，那么记住他们只在此作用域中可以访问。他也用于exception_object_pointer_name变量。<br /><br /><b>ASSERT<br />ASSERT(booleanExpression)</b><br /><i><u>说明：</u></i><br />　　计算变量的值。如果结构的值为0，那么此宏便打印一个诊断消息并且成讯运行失败。如果条件为非0，那么什么也不做。 诊断消息的形式为： assertion failed in file in line 其中name是元文件名，num是源文件中运行失败的中断号。在Release版中，ASSERT不计算表达式的值也就不中断程序。如果必须计算此表达式的值且不管环境如何那么用VERIFY代替ASSERT。<br /><u><i>注释：</i></u><br />　　ASSERT只能在Debug版中用<br /><br /><b>ASSERT_VAILD<br />ASSERT_VAILD(pObject)</b><br /><u><i>说明：</i></u><br />　　用于检测关于对象的内部状态的有效性。ASSERT_VALID调用此对象的AssertValid成员函数（把它们作为自己的变量来传递）。在 Release版中ASSERT_VALID什么也不做。在DEBUG版中，他检查指针，以不同于NULL的方式进行检查，并调用对象自己的 AssertValid成员函数。如果这些检测中有任何一个失败的话，那么他会以与ASSERT相同的方法显示一个警告的消息。<br /><u><i>注释：</i></u><br />　　此函数只在DEBUG版中有效。<br /><br /><b>BEGIN_MESSAGE_MAP<br />BEGIN_MESSAGE_MAP(the class,baseclass)</b><br /><i><u>说明：</u></i><br />　　使用BEGIN_MESSAGE_MAP开始用户消息映射的定义。在定义用户类函数的工具（.cpp）文件中，以BEGIN_MESSAGE_MAP宏开始消息映射，然后为每个消息处理函数增加宏项，接着以END_MESSAGE_MAP宏完成消息映射。<br /><br /><b>CATCH<br />CATCH(exception_class,exception_object_pointer_name)</b><br /><u><i>说明：</i></u><br />　　使用此用定义一个代码块，此代码用来获取当前TRY块中都一个异常类型。异常处理代码可以访问异常对象，如何合适的话，就会得到关于异常的特殊原因的更多消息。调用THROW_LAST宏以把处理过程一下一个外部异常框架，如果exception-class是类CExceptioon,那么会获取所有异常类型。用户可以使用CObject::IsKindOf成员函数以确定那个特别异常被排除。一种获取异常的最好方式是使用顺序的AND_CATCH语句，每个带一个不同的异常类型。此异常类型的指针由宏定义，用户不必定义。<br /><u><i>注释：</i></u><br />　　此CATCH块被定义作一个C++范围（由花括号描述）。如用户在此范围定义变量，那么它们只在吃范围内可以访问。他还可以用于异常对象的指针名。<br /><br /><b>DEBUG_NEW</b><br /><b>#define new DEBUG_NEW</b><br /><i><u>说明：</u></i><br />　　帮助查找内存错误。用户在程序中使用DEBUG_NEW,用户通常使用new运算符来从堆上分配。在Debug模式下（但定义了一个DEBUG符号）， DEBUG_NEW为它分配的每个对象记录文件名和行号。然后，在用户使用CMemoryState::DumpAllObjectSince成员函数时，每个以DEBUG_NEW分配的对象分配的地方显示出文件名和行号。 为了使用DEBUG_NEW,应在用户的资源文件中插入以下指令： #define new DEBUG_NEW 一旦用户插入本指令，预处理程序将在使用new的地方插入DEBUG_NEW，而MFC作其余的工作。但用户编译自己的程序的一个发行版时， DEBUG_NEW便进行简单的new操作，而且不产生文件名和行号消息。<br /><br /><b>DECLARE_DYNAMIC<br />DECLARE_DYNAMIC(class_name)</b><br /><i><u>说明：</u></i><br />　　但从CObject派生一个类时，此宏增加关于一个对象类的访问运行时间功能。把DECLARE_DYNAMIC宏加入类的头文件中，然后在全部需要访问词类对象的.CPP文件中都包含此模块。如果像所描述那样使用DELCARE_DYNAMIC和IMPLEMENT_DYNAMIC宏，那么用户便可使用 RUNTIME_CLASS宏和CObject::IsKindOf函数以在运行时间决定对象类。如果DECLARE_DYNAMIC包含在类定义中，那么IMPLEMETN_DYNAMIC必须包含在类工具中。<br /><br /><b>DECLARE_DYNCREATE<br />DECLARE_DYNCREATE(class_name)</b><br /><u><i>说明：</i></u><br />　　使用DECLARE_DYNCRETE宏以便允许CObject派生类的对象在运行时刻自动建立。主机使用此功能自动建立新对象，例如，但它在串行化过程中从磁盘读一个对象时，文件及视图和框架窗应该支持动态建立，因为框架需要自动建立它。把DECLARE_DYNCREATE宏加入类的.H文件中，然后在全部需要访问此类对象的.CPP文件中包含这一模式。如果DECLARE_DYNCREATE包含在类定义中，那么 IMPLEMENT_DYNCREATE必须包含在类工具中。<br /><br /><b>DECLARE_MESSAGE_MAP<br />DECLARE_MESSAGE_MAP()</b><br /><u><i>说明：</i></u><br />　　用户程序中的每个CCmdTarget派生类必须提供消息映射以处理消息。在类定义的末尾使用DECLARE_MESSAGE_MAP宏。接着，在定义类成员函数的.CPP文件中，使用BEGIN_MESSAGE_MAP宏，每个用户消息处理函数的宏项下面的列表以及END_MESSAGE_MAP宏。<br /><u><i>注释：</i></u><br />　　如果在DECLARE_MESSAGE_MAP之后定义任何一个成员，那么必须为他们指定一个新存取类型（公共的，私有的，保护的）。<br /><br /><b>DECLARE_SERIAL<br />DECLARE_SERIAL(class_name)</b><br /><u><i>说明：</i></u><br />　　DECLARE_SERIAL 为一个可以串行化的CObject派生类产生必要的C++标题代码。串行化是把某个对象的内容从一个文件读出和写入一文件。在.H文件中使用 DECLARE_SERIAL宏，接着在需要访问此类对象的全部.CPP文件中包含此文件。如果DECLARE_SERIAL包含在类定义中，那么 IMPLEMENT_SERIAL必须包含在类工具中。DECLARE_SERIAL宏包含全部DECLARE_DYNAMIC, IMPLEMENT_DYCREATE的功能。<br /><br /><b>END_CATCH<br />END_CATCH</b><br /><i><u>说明：</u></i><br />　　标识最后的CATCH或AND_CATCH块的末尾。<br /><br /><b>END_MESSAGE_MAP<br />END_MESSAGE_MAP</b><br /><i><u>说明：</u></i><br />使用END_MESSAGE_MAP宏结束用户的消息映射定义<br /><br /><b>IMPLEMENT_DYNAMIC<br />IMPLEMENT_DYNAMIC(class_name,base_class_name)</b><br /><i><u>说明：</u></i><br />　　通过运行时在串行结构中为动态CObject派生类访问类名和位置来产生必要的C++代码。在.CPP文件中使用IMPLEMENT_DYNAMIC宏，接着一次链接结果对象代码<br /><br /><b>IMPLEMENT_DYNCREATE<br />IMPLEMENT_DYNCREATE(class_name,base_class_name)</b><br /><i><u>说明：</u></i><br />　　通过DECLARE_DYNCREATE宏来使用IMPLEMENT_DYNCREATE宏，以允许CObject派生类对象在运行时自动建立。主机使用此功能自动建立对象，例如，但它在串行化过程中从磁盘读去一个对象时，他在类工具里加入IMPLEMENT_DYNCREATE宏。若用户使用 DECLARE_DYNCREATE和IMPLEMENT_DYNCREATE宏,那么接着使用RUNTIME_CLASS宏和CObject:: IsKindOf成员函数以在运行时确定对象类。若declare_dyncreate包含在定义中，那么IMPLEMENT_DYNCREATE必须包含在类工具中。<br /><br /><b>IMPLEMENT_SERIAL<br />IMPLEMENT_SERIAL(class_name,base_class_name,wSchema)</b><br /><i><u>说明：</u></i><br />　　通过运行时在串行结构中动态CObject派生类访问类名和位置来建立必要的C++代码。在.CPP文件中使用IMPLEMENT_SERIAL宏，然后一次链接结果对象代码。<br /><br /><b>ON_COMMAND<br />ON_COMMAND(id,memberFxn)</b><br /><i><u>说明：</u></i><br />　　此宏通过ClassWizard或手工插入一个消息映射。它表明那个函数将从一个命令用户接口（例如一个菜单项或toolbar按钮）处理一个命令消息。当一个命令对象通过指定的ID接受到一个Windows WM_COMMAND消息时，ON_COMMAND将调用成员函数memberFxn处理此消息。在用户的消息映射中，对于每个菜单或加速器命令（必须被映射到一个消息处理函数）应该确实有一个ON_COMMAND宏语句。<br /><br /><b>ON_CONTROL<br />ON_CONTROL(wNotifyCode,id,memberFxn)</b><br /><i><u>说明：</u></i><br />　　表明哪个函数将处理一个常规控制表示消息。控制标识消息是那些从一个控制夫发送到母窗口的消息。<br /><br /><b>ON_MESSAGE<br />ON_MESSAGE(message,memberFxn)</b><br /><i><u>说明：</u></i><br />　　指明哪个函数将处理一用户定义消息。用户定义消息通常定义在WM_USER到0x7FF范围内。用户定义消息是那些不是标准Windows WM_MESSAGE消息的任何消息。在用户的消息映射中，每个必须被映射到一个消息处理函数。用户定义消息应该有一个ON_MESSAGE宏语句。<br /><br /><b>ON_REGISTERED_MESSAGE<br />ON_REGISTERED_MESSAGE(nmessageVarible,memberFxn)</b><br /><u><i>说明：</i></u><br />　　Windows的RegisterWindowsMesage函数用于定义一个新窗口消息，此消息保证在整个系统中是唯一的。此宏表明哪个函数处理已注册消息。变量nMessageViable应以NEAR修饰符来定义。<br /><b><br />ON_UPDATE_COMMAND_UI<br />ON_UPDATE_COMMAND_UI(id，memberFxn)</b><br /><i><u>说明：</u></i><br />　　此宏通常通过ClassWizard被插入一个消息映射，以指明哪个函数将处理一个用户接口个更改命令消息。在用户的消息映射中，每个用户接口更改命令（比讯被映射到一个消息处理函数）应该有一个ON_UPDATE_COMMAND_UI宏语句。<br /><br /><b>ON_VBXEVENT<br />ON_VBXEVENT(wNotifyCode,memberFxn)</b><br /><i><u>说明：</u></i><br />　　此宏通常通过ClassWizard被插入一个消息映射，以指明哪个函数将处理一个来自VBX控制的消息。在用户的消息映射中每个被映射到一消息处理函数的VBX控制消息应该有一个宏语句。<br /><br /><b>RUNTIME_CLASS<br />RUNTIME_CLASS(class_name)</b><br /><i><u>说明：</u></i><br />　　使用此宏从c++类民众获取运行时类结构。RUNTIME_CLASS为由class_name指定的类返回一个指针到CRuntimeClass结构。只有以DECLARE_DYNAMIC,DECLARE_DYNCREATE或DECLARE_SERIAL定义的CObject派生类才返回到一个 CRuntimeClass结构的指针。<br /><br /><b>THROW<br />THROW(exception_object_pointer)</b><br /><i><u>说明：</u></i><br />　　派出指定的异常。THROW中断程序的运行，把控制传递给用户程序中的相关的CATCH块。如果用户没有提供CATCH块，那么控制被传递到一个MFC模块，他打印出一个错误并终止运行。<br /><br /><b>THROW_LAST<br />THROW_LAST()</b><br /><i><u>说明：</u><u><br /></u></i>　　此宏允许用户派出一个局部建立的异常。如果用户试图排除一个刚发现的异常，那么一般此异常将溢出并被删除。使用THROW_LAST,此异常被直接传送到下一个CATCH处理程序。<br /><br /><b>TRACE<br />TRACE(exp)</b><br /><i><u>说明：</u></i><br />　　把一个格式化字符串送到转储设备，例如，文件或调试监视器，而提供与printf相似的功能。同MS_DOS下C程序的printf一样，TRACE宏是一个在程序运行时跟踪变量值的方便形式。在DEBUG环境中，TRACE宏输出到afxDump。在Release版中他不做任何工作。<br /><i><u>注释：</u></i><br />　　此宏只在MFC的DEBUG版中有效。<br /><b><br />TRACE0<br />TRACE0(exp)</b><br /><i><u>说明：</u></i><br />　　与TRACE 相似，但他把跟踪字符串放在代码段中，而不是DGROUP,因此使用少的DGROUP空间。TRACE0是一组跟踪宏的一个变体，这些宏可用于调试输出。这一组包括TRACE0,TRACE1,TRACE2和TRACE3,这些宏不同在于所取参数的数目不同。TRACE0只取一个格式化字符串并可用于简单文本消息。TRACE1取一格式化字符串加上一个变量——一个将转储的变量。同样，TRACE2,TRACE3分别取2个或3个参数（在格式化字符串之后）。如果用户以便以了应用程序的发行版，那么它只把数据转储到afxDump。<br /><i><u>注释：</u></i><br />　　此宏只在MFC的DEBUG中有效。<br /><br /><br /><b>TRACE1，TRACE2，TRACE3<br />TRACE1(exp,param1)，TRACE2(exp,param1,param2)，TRACE3(exp,param1,param1,param2,param3)</b><br /><i><u>说明：</u></i><br />　　参见TRACE0<br /><br /><b>TRY<br />TRY</b><br /><i><u>说明：</u></i><br />　　使用此宏建立一TRY块。一个TRY识别一个可排除异常的代码块。这些异常在随后的CATCH和AND_CATCH块处理。传递是允许的：异常可以传递一个外部TRY块，或者忽略它们或者使用THROW_LAST宏。<br /><br /><b>VERIFY<br />VERIFY(booleanExpression)</b><br /><i><u>说明：</u></i><br />　　在MFC 的DEBUG版中，VERIFY宏计算它的变量值。如果结果为0，那么宏打印一个诊断消息并中止程序。如果条件不为0，那么什么工作也不作。诊断有如下形式： assertion failed in file in line 其中name是源文件的名字，num是在源文件中失败的中止行号。在MFC的Release版中，VERIFY计算表达式值但不打印或中止程序。例如：如果表达式是个函数调用，那么调用成功。 </div>
<img src ="http://www.cppblog.com/deadpunk/aggbug/20670.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/deadpunk/" target="_blank">活着就是折腾，所以当然要骠悍的折腾</a> 2007-03-27 09:25 <a href="http://www.cppblog.com/deadpunk/archive/2007/03/27/20670.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在list control中加入鼠标右键弹出菜单并做出删除所点的item项</title><link>http://www.cppblog.com/deadpunk/archive/2007/03/09/19489.html</link><dc:creator>活着就是折腾，所以当然要骠悍的折腾</dc:creator><author>活着就是折腾，所以当然要骠悍的折腾</author><pubDate>Fri, 09 Mar 2007 05:31:00 GMT</pubDate><guid>http://www.cppblog.com/deadpunk/archive/2007/03/09/19489.html</guid><wfw:comment>http://www.cppblog.com/deadpunk/comments/19489.html</wfw:comment><comments>http://www.cppblog.com/deadpunk/archive/2007/03/09/19489.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/deadpunk/comments/commentRss/19489.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/deadpunk/services/trackbacks/19489.html</trackback:ping><description><![CDATA[
		<p>xxxDlg.h文件中:<br />CListCtrl m_lstSorting;<br /><br />afx_msg void OnMenuDelete();      //手动<br />// Generated message map functions<br />//{{AFX_MSG(CAlarmStoreSimulatorDlg)<br />...<br />afx_msg void OnRclickLisSorting(NMHDR* pNMHDR, LRESULT* pResult);<br />//}}AFX_MSG<br />DECLARE_MESSAGE_MAP()<br /><br /><br />xxxDlg.cpp中:<br /><br /> BEGIN_MESSAGE_MAP(CAlarmStoreSimulatorDlg, CDialog)<br />  //{{AFX_MSG_MAP(CAlarmStoreSimulatorDlg)<br />  ...<br />  ON_NOTIFY(NM_RCLICK, IDC_LIS_SORTING, OnRclickLisSorting)<br />  ON_COMMAND_RANGE(ID_MENUITEM_DELETE, ID_MENUITEM_DELETE, OnMenuDelete)<br />  //}}AFX_MSG_MAP<br />  END_MESSAGE_MAP()<br /><br /> void CAlarmStoreSimulatorDlg::OnRclickLisSorting(NMHDR* pNMHDR, LRESULT* pResult) <br /> {<br />  // TODO: Add your control notification handler code here<br />  NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;<br />  if(pNMListView-&gt;iItem != -1)<br />  {<br />   DWORD dwPos = GetMessagePos();<br />   CPoint point( LOWORD(dwPos), HIWORD(dwPos) );<br />   <br />   CMenu menu;<br />   VERIFY( menu.LoadMenu( IDR_MENU_POPUP ) );      //IDR_MENU_POPUP是新建菜单ID<br />   CMenu* popup = menu.GetSubMenu(0);<br />   ASSERT( popup != NULL );<br />   popup-&gt;TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this );<br />  } <br />  *pResult = 0;<br /> }<br /> <br /> void CAlarmStoreSimulatorDlg::OnMenuDelete()<br /> {<br />  int iItemSel = m_lstSorting.GetNextItem(-1, LVIS_SELECTED);   <br />  if(iItemSel != -1)   <br />  {   <br />   m_lstSorting.DeleteItem(iItemSel);   //delete selected item in the list control<br />  }   <br /> }<br /><br />备注:<br />学会了用这个消息映射ON_COMMAND_RANGE(ID_MENUITEM_DELETE, ID_MENUITEM_DELETE, OnMenuDelete)去响应弹出菜单的事件响应,ID_MENUITEM_DELETE是菜单button的ID,好像还可以是一个ID区域, OnMenuDelete是消息响应函数.<br /> </p>
<img src ="http://www.cppblog.com/deadpunk/aggbug/19489.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/deadpunk/" target="_blank">活着就是折腾，所以当然要骠悍的折腾</a> 2007-03-09 13:31 <a href="http://www.cppblog.com/deadpunk/archive/2007/03/09/19489.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]CListCtrl 使用技巧 </title><link>http://www.cppblog.com/deadpunk/archive/2007/03/08/19433.html</link><dc:creator>活着就是折腾，所以当然要骠悍的折腾</dc:creator><author>活着就是折腾，所以当然要骠悍的折腾</author><pubDate>Thu, 08 Mar 2007 08:22:00 GMT</pubDate><guid>http://www.cppblog.com/deadpunk/archive/2007/03/08/19433.html</guid><wfw:comment>http://www.cppblog.com/deadpunk/comments/19433.html</wfw:comment><comments>http://www.cppblog.com/deadpunk/archive/2007/03/08/19433.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/deadpunk/comments/commentRss/19433.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/deadpunk/services/trackbacks/19433.html</trackback:ping><description><![CDATA[
		<p>作者：lixiaosan<br />时间：04/06/2006<br /></p>
		<p>以下未经说明，listctrl默认view 风格为report</p>
		<p>相关类及处理函数<br /></p>
		<p>MFC：CListCtrl类</p>
		<p>SDK：以 “ListView_”开头的一些宏。如 ListView_InsertColumn<br /></p>
		<hr style="WIDTH: 100%; HEIGHT: 2px" />
		<h3>
				<span style="COLOR: rgb(153,51,102)">
						<span style="COLOR: rgb(153,51,0)">1. CListCtrl 风格</span>
				</span>
		</h3>
		<p>      LVS_ICON: 为每个item显示大图标<br />      LVS_SMALLICON: 为每个item显示小图标<br />      LVS_<a name="baidusnap0"></a><b style="COLOR: black; BACKGROUND-COLOR: #ffff66">LIST</b>: 显示一列带有小图标的item<br />      LVS_REPORT: 显示item详细资料</p>
		<p>      直观的理解：windows资源管理器，“查看”标签下的“大图标，小图标，列表，详细资料”</p>
		<p>
				<br />
		</p>
		<hr style="WIDTH: 100%; HEIGHT: 2px" />
		<h3>
				<span style="COLOR: rgb(153,51,0)">2. 设置listctrl 风格及扩展风格</span>
		</h3>
		<p>      LONG lStyle;<br />      lStyle = GetWindowLong(m_<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">list</b>.m_hWnd, GWL_STYLE);//获取当前窗口style<br />      lStyle &amp;= ~LVS_TYPEMASK; //清除显示方式位<br />      lStyle |= LVS_REPORT; //设置style<br />      SetWindowLong(m_<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">list</b>.m_hWnd, GWL_STYLE, lStyle);//设置style<br /> <br />      DWORD dwStyle = m_<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">list</b>.GetExtendedStyle();<br />      dwStyle |= LVS_EX_FULLROWSELECT;//选中某行使整行高亮（只适用与report风格的listctrl）<br />      dwStyle |= LVS_EX_GRIDLINES;//网格线（只适用与report风格的listctrl）<br />      dwStyle |= LVS_EX_CHECKBOXES;//item前生成checkbox控件<br />      m_<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">list</b>.SetExtendedStyle(dwStyle); //设置扩展风格<br />  <br />      注：listview的style请查阅msdn<br />      <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wceshellui5/html/wce50lrflistviewstyles.asp">http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wceshellui5/html/wce50lrflistviewstyles.asp</a><br /></p>
		<p> </p>
		<hr style="WIDTH: 100%; HEIGHT: 2px" />
		<h3>
				<span style="COLOR: rgb(153,51,0)">3. 插入数据</span>
		</h3>
		<p>
				<span style="COLOR: rgb(153,51,0)">
				</span>
				<span style="COLOR: rgb(153,51,0)">
				</span>      m_<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">list</b>.InsertColumn( 0, "ID", LVCFMT_LEFT, 40 );//插入列<br />      m_<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">list</b>.InsertColumn( 1, "NAME", LVCFMT_LEFT, 50 );<br />      int nRow = m_<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">list</b>.InsertItem(0, “11”);//插入行<br />      m_<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">list</b>.SetItemText(nRow, 1, “jacky”);//设置数据<br /></p>
		<p> </p>
		<hr style="WIDTH: 100%; HEIGHT: 2px" />
		<h3>
				<span style="COLOR: rgb(51,102,255)">
						<span style="COLOR: rgb(153,51,0)">4. 一直选中item</span>
				</span>
		</h3>
		<span style="FONT-WEIGHT: bold">    </span>选中style中的Show selection always，或者在上面第2点中设置LVS_SHOWSELALWAYS<br /><br /><br /><hr style="WIDTH: 100%; HEIGHT: 2px" /><h3><span style="COLOR: rgb(153,51,0)">5. 选中和取消选中一行</span></h3><p>    int nIndex = 0;<br />    //选中<br />    m_<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">list</b>.SetItemState(nIndex, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED);<br />    //取消选中<br />    m_<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">list</b>.SetItemState(nIndex, 0, LVIS_SELECTED|LVIS_FOCUSED);<br /> </p><hr style="WIDTH: 100%; HEIGHT: 2px" /><h3><span style="COLOR: rgb(153,51,0)">6. 得到listctrl中所有行的checkbox的状态</span></h3><p>      m_<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">list</b>.SetExtendedStyle(LVS_EX_CHECKBOXES);<br />      CString str;<br />      for(int i=0; i&lt;m_<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">list</b>.GetItemCount(); i++)<br />      {<br />           if( m_<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">list</b>.GetItemState(i, LVIS_SELECTED) == LVIS_SELECTED || m_<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">list</b>.GetCheck(i))<br />           {<br />                str.Format(_T("第%d行的checkbox为选中状态"), i);<br />                AfxMessageBox(str);<br />           }<br />      }<br /></p><p><br /></p><hr style="WIDTH: 100%; HEIGHT: 2px" /><h3><span style="COLOR: rgb(153,51,0)">7. 得到listctrl中所有选中行的序号</span></h3><h3><span style="COLOR: rgb(153,51,0)"></span></h3><p><span style="COLOR: rgb(153,51,0)"><br /></span>      方法一：<br />      CString str;<br />      for(int i=0; i&lt;m_<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">list</b>.GetItemCount(); i++)<br />      {<br />           if( m_<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">list</b>.GetItemState(i, LVIS_SELECTED) == LVIS_SELECTED )<br />           {<br />                str.Format(_T("选中了第%d行"), i);<br />                AfxMessageBox(str);<br />           }<br />      }</p><p>      方法二：<br />      POSITION pos = m_<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">list</b>.GetFirstSelectedItemPosition();<br />      if (pos == NULL)<br />           TRACE0("No items were selected!\n");<br />      else<br />      {<br />           while (pos)<br />           {<br />                int nItem = m_<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">list</b>.GetNextSelectedItem(pos);<br />                TRACE1("Item %d was selected!\n", nItem);<br />                // you could do your own processing on nItem here<br />           }<br />      }<br /></p><p><br /></p><hr style="WIDTH: 100%; HEIGHT: 2px" /><h3><span style="COLOR: rgb(153,51,0)">8. 得到item的信息</span></h3><p>      TCHAR szBuf[1024];<br />      LVITEM lvi;<br />      lvi.iItem = nItemIndex;<br />      lvi.iSubItem = 0;<br />      lvi.mask = LVIF_TEXT;<br />      lvi.pszText = szBuf;<br />      lvi.cchTextMax = 1024;<br />      m_<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">list</b>.GetItem(&amp;lvi);</p><p>      关于得到设置item的状态，还可以参考msdn文章<br />      Q173242: Use Masks to Set/Get Item States in CListCtrl<br />               <a href="http://support.microsoft.com/kb/173242/en-us">http://support.microsoft.com/kb/173242/en-us</a><br /></p><p><br /></p><hr style="WIDTH: 100%; HEIGHT: 2px" /><h3><span style="COLOR: rgb(51,102,255)"><span style="COLOR: rgb(153,51,0)">9. 得到listctrl的所有列的header字符串内容</span></span></h3><p>      LVCOLUMN lvcol;<br />      char  str[256];<br />      int   nColNum;<br />      CString  strColumnName[4];//假如有4列</p><p>      nColNum = 0;<br />      lvcol.mask = LVCF_TEXT;<br />      lvcol.pszText = str;<br />      lvcol.cchTextMax = 256;<br />      while(m_<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">list</b>.GetColumn(nColNum, &amp;lvcol))<br />      { <br />           strColumnName[nColNum] = lvcol.pszText;<br />           nColNum++;<br />      }<br /></p><p><br /></p><hr style="WIDTH: 100%; HEIGHT: 2px" /><h3><span style="COLOR: rgb(153,51,0)">10. 使listctrl中一项可见，即滚动滚动条</span></h3>    m_<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">list</b>.EnsureVisible(i, FALSE);<br /><br /><hr style="WIDTH: 100%; HEIGHT: 2px" /><h3><span style="COLOR: rgb(153,51,0)">11. 得到listctrl列数</span></h3>    int nHeadNum = m_<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">list</b>.GetHeaderCtrl()-&gt;GetItemCount();<br /><br /><hr style="WIDTH: 100%; HEIGHT: 2px" /><h3><span style="COLOR: rgb(153,51,0)">12. <a name="baidusnap4"></a><b style="COLOR: black; BACKGROUND-COLOR: #ff66ff">删除</b>所有列</span></h3><p>      方法一：<br />         while ( m_<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">list</b>.DeleteColumn (0))<br />       因为你<b style="COLOR: black; BACKGROUND-COLOR: #ff66ff">删除</b>了第一列后，后面的列会依次向上移动。</p><p>      方法二：<br />      int nColumns = 4;<br />      for (int i=nColumns-1; i&gt;=0; i--)<br />          m_<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">list</b>.DeleteColumn (i);<br /></p><p><br /></p><hr style="WIDTH: 100%; HEIGHT: 2px" /><h3><span style="COLOR: rgb(153,51,0)">13. 得到单击的listctrl的行列号</span></h3><p>      添加listctrl控件的NM_CLICK消息相应函数<br />      void CTest6Dlg::OnClickList1(NMHDR* pNMHDR, LRESULT* pResult)<br />      {<br />           // 方法一：<br />           /*<br />           DWORD dwPos = GetMessagePos();<br />           CPoint point( LOWORD(dwPos), HIWORD(dwPos) );<br />   <br />           m_<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">list</b>.ScreenToClient(&amp;point);<br />   <br />           LVHITTESTINFO lvinfo;<br />           lvinfo.pt = point;<br />           lvinfo.flags = LVHT_ABOVE;<br />     <br />           int nItem = m_<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">list</b>.SubItemHitTest(&amp;lvinfo);<br />           if(nItem != -1)<br />           {<br />                CString strtemp;<br />                strtemp.Format("单击的是第%d行第%d列", lvinfo.iItem, lvinfo.iSubItem);<br />                AfxMessageBox(strtemp);<br />           }<br />          */<br />   <br />          // 方法二:<br />          /*<br />           NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;<br />           if(pNMListView-&gt;iItem != -1)<br />           {<br />                CString strtemp;<br />                strtemp.Format("单击的是第%d行第%d列",<br />                                pNMListView-&gt;iItem, pNMListView-&gt;iSubItem);<br />                AfxMessageBox(strtemp);<br />           }<br />          */<br />           *pResult = 0;<br />      }<br /></p><p> </p><hr style="WIDTH: 100%; HEIGHT: 2px" /><h3><span style="COLOR: rgb(153,51,0)">14. 判断是否点击在listctrl的checkbox上</span></h3><p>      添加listctrl控件的NM_CLICK消息相应函数<br />      void CTest6Dlg::OnClickList1(NMHDR* pNMHDR, LRESULT* pResult)<br />      {<br />           DWORD dwPos = GetMessagePos();<br />           CPoint point( LOWORD(dwPos), HIWORD(dwPos) );<br />   <br />           m_<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">list</b>.ScreenToClient(&amp;point);<br />   <br />           LVHITTESTINFO lvinfo;<br />           lvinfo.pt = point;<br />           lvinfo.flags = LVHT_ABOVE;<br />     <br />           UINT nFlag;<br />           int nItem = m_<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">list</b>.HitTest(point, &amp;nFlag);<br />           //判断是否点在checkbox上<br />           if(nFlag == LVHT_ONITEMSTATEICON)<br />           {<br />                AfxMessageBox("点在listctrl的checkbox上");<br />           } <br />           *pResult = 0;<br />      }<br /></p><p><br /></p><hr style="WIDTH: 100%; HEIGHT: 2px" /><h3><span style="COLOR: rgb(153,51,0)">15. <a name="baidusnap2"></a><b style="COLOR: black; BACKGROUND-COLOR: #99ff99">右键</b>点击listctrl的item弹出菜单</span></h3><p>      添加listctrl控件的NM_RCLICK消息相应函数<br />      void CTest6Dlg::OnRclickList1(NMHDR* pNMHDR, LRESULT* pResult)<br />      {<br />           NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;<br />           if(pNMListView-&gt;iItem != -1)<br />           {<br />                DWORD dwPos = GetMessagePos();<br />                CPoint point( LOWORD(dwPos), HIWORD(dwPos) );<br />    <br />                CMenu menu;<br />                VERIFY( menu.LoadMenu( IDR_MENU1 ) );<br />                CMenu* popup = menu.GetSubMenu(0);<br />                ASSERT( popup != NULL );<br />                popup-&gt;TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this );<br />           } <br />           *pResult = 0;<br />  }<br /></p><p><br /></p><p> </p><hr style="WIDTH: 100%; HEIGHT: 2px" /><h3><span style="COLOR: rgb(153,51,0)">16. item切换焦点时(包括用键盘和鼠标切换item时)，状态的一些变化顺序</span></h3><p>      添加listctrl控件的LVN_ITEMCHANGED消息相应函数<br />      void CTest6Dlg::OnItemchangedList1(NMHDR* pNMHDR, LRESULT* pResult)<br />      {<br />           NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;<br />           // TODO: Add your <a name="baidusnap1"></a><b style="COLOR: black; BACKGROUND-COLOR: #a0ffff">control</b> notification handler code here<br />    <br />           CString sTemp;<br />  <br />           if((pNMListView-&gt;uOldState &amp; LVIS_FOCUSED) == LVIS_FOCUSED &amp;&amp; <br />            (pNMListView-&gt;uNewState &amp; LVIS_FOCUSED) == 0)<br />           {<br />                sTemp.Format("%d losted focus",pNMListView-&gt;iItem);<br />           }<br />           else if((pNMListView-&gt;uOldState &amp; LVIS_FOCUSED) == 0 &amp;&amp;<br />               (pNMListView-&gt;uNewState &amp; LVIS_FOCUSED) == LVIS_FOCUSED)<br />           {<br />                sTemp.Format("%d got focus",pNMListView-&gt;iItem);<br />           } <br />  <br />           if((pNMListView-&gt;uOldState &amp; LVIS_SELECTED) == LVIS_SELECTED &amp;&amp;<br />            (pNMListView-&gt;uNewState &amp; LVIS_SELECTED) == 0)<br />           {<br />                sTemp.Format("%d losted selected",pNMListView-&gt;iItem);<br />           }<br />           else if((pNMListView-&gt;uOldState &amp; LVIS_SELECTED) == 0 &amp;&amp;<br />            (pNMListView-&gt;uNewState &amp; LVIS_SELECTED) == LVIS_SELECTED)<br />           {<br />                sTemp.Format("%d got selected",pNMListView-&gt;iItem);<br />           }<br />    <br />           *pResult = 0;<br />      }</p><br /><br /><hr style="WIDTH: 100%; HEIGHT: 2px" /><h3><span style="COLOR: rgb(153,51,0)">17. 得到另一个进程里的listctrl控件的item内容</span><span style="COLOR: rgb(51,102,255)"></span></h3><h3><span style="COLOR: rgb(51,102,255)"></span></h3><span style="COLOR: rgb(51,102,255)"></span><a href="http://www.codeproject.com/threads/int64_memsteal.asp">http://www.codeproject.com/threads/int64_memsteal.asp</a><br /><br /><br /><hr style="WIDTH: 100%; HEIGHT: 2px" /><h3><span style="COLOR: rgb(51,102,255)"><span style="COLOR: rgb(153,51,0)">18. 选中listview中的item</span></span></h3>Q131284: How To Select a Listview Item Programmatically<br /><a href="http://support.microsoft.com/kb/131284/en-us">http://support.microsoft.com/kb/131284/en-us</a><br /><br /><br /><hr style="WIDTH: 100%; HEIGHT: 2px" /><h3><span style="COLOR: rgb(153,51,0)">19. 如何在CListView中使用CListCtrl的派生类</span></h3><p><a href="http://www.codeguru.com/cpp/controls/listview/introduction/article.php/c919/">http://www.codeguru.com/cpp/controls/listview/introduction/article.php/c919/</a><br /></p><p><br /></p><hr style="WIDTH: 100%; HEIGHT: 2px" /><h3><span style="COLOR: rgb(153,51,0)">20. listctrl的subitem添加图标</span></h3><p>      m_<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">list</b>.SetExtendedStyle(LVS_EX_SUBITEMIMAGES);<br />      m_<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">list</b>.SetItem(..); //具体参数请参考msdn<br /></p><p> </p><hr style="WIDTH: 100%; HEIGHT: 2px" /><h3><span style="COLOR: rgb(153,51,0)">21. 在CListCtrl显示文件，并根据文件类型来显示图标</span></h3><p>      网上找到的代码，share<br />      BOOL CTest6Dlg::OnInitDialog()<br />      {<br />           CDialog::OnInitDialog();<br />   <br />           HIMAGELIST himlSmall;<br />           HIMAGELIST himlLarge;<br />           SHFILEINFO sfi;<br />           char  cSysDir[MAX_PATH];<br />           CString  strBuf;<br />  <br />           memset(cSysDir, 0, MAX_PATH);<br />   <br />           GetWindowsDirectory(cSysDir, MAX_PATH);<br />           strBuf = cSysDir;<br />           sprintf(cSysDir, "%s", strBuf.Left(strBuf.Find("<a href="file://%22)+1/">file://%22)+1/</a>));<br />  <br />           himlSmall = (HIMAGELIST)SHGetFileInfo ((LPCSTR)cSysDir,  <br />                      0,  <br />                      &amp;sfi, <br />                      sizeof(SHFILEINFO),  <br />                      SHGFI_SYSICONINDEX | SHGFI_SMALLICON );<br />   <br />           himlLarge = (HIMAGELIST)SHGetFileInfo((LPCSTR)cSysDir,  <br />                      0,  <br />                      &amp;sfi,  <br />                      sizeof(SHFILEINFO),  <br />                      SHGFI_SYSICONINDEX | SHGFI_LARGEICON);<br />   <br />           if (himlSmall &amp;&amp; himlLarge)<br />           {<br />                ::SendMessage(m_<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">list</b>.m_hWnd, LVM_SETIMAGELIST,<br />                             (WPARAM)LVSIL_SMALL, (LPARAM)himlSmall);<br />                ::SendMessage(m_<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">list</b>.m_hWnd, LVM_SETIMAGELIST,<br />                             (WPARAM)LVSIL_NORMAL, (LPARAM)himlLarge);<br />           }<br />           return TRUE;  // return TRUE  unless you set the focus to a <b style="COLOR: black; BACKGROUND-COLOR: #a0ffff">control</b><br />      }<br />  <br />      void CTest6Dlg::AddFiles(LPCTSTR lpszFileName, BOOL bAddToDocument)<br />      {<br />           int nIcon = GetIconIndex(lpszFileName, FALSE, FALSE);<br />           CString strSize;<br />           CFileFind filefind;<br />  <br />           //  get file size<br />           if (filefind.FindFile(lpszFileName))<br />           {<br />                filefind.FindNextFile();<br />                strSize.Format("%d", filefind.GetLength());<br />           }<br />           else<br />                strSize = "0";<br />   <br />           // split path and filename<br />           CString strFileName = lpszFileName;<br />           CString strPath;<br />  <br />           int nPos = strFileName.ReverseFind('\\');<br />           if (nPos != -1)<br />           {<br />                strPath = strFileName.Left(nPos);<br />                strFileName = strFileName.Mid(nPos + 1);<br />           }<br />   <br />           // insert to <b style="COLOR: black; BACKGROUND-COLOR: #ffff66">list</b><br />           int nItem = m_<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">list</b>.GetItemCount();<br />           m_<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">list</b>.InsertItem(nItem, strFileName, nIcon);<br />           m_<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">list</b>.SetItemText(nItem, 1, strSize);<br />           m_<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">list</b>.SetItemText(nItem, 2, strFileName.Right(3));<br />           m_<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">list</b>.SetItemText(nItem, 3, strPath);<br />      }<br />  <br />      int CTest6Dlg::GetIconIndex(LPCTSTR lpszPath, BOOL bIsDir, BOOL bSelected)<br />      {<br />           SHFILEINFO sfi;<br />           memset(&amp;sfi, 0, sizeof(sfi));<br />   <br />           if (bIsDir)<br />           {<br />            SHGetFileInfo(lpszPath,  <br />                         FILE_ATTRIBUTE_DIRECTORY,  <br />                         &amp;sfi,  <br />                         sizeof(sfi),  <br />                         SHGFI_SMALLICON | SHGFI_SYSICONINDEX |<br />                         SHGFI_USEFILEATTRIBUTES |(bSelected ? SHGFI_OPENICON : 0));  <br />            return  sfi.iIcon;<br />           }<br />           else<br />           {<br />            SHGetFileInfo (lpszPath,  <br />                         FILE_ATTRIBUTE_NORMAL,  <br />                         &amp;sfi,  <br />                         sizeof(sfi),  <br />                         SHGFI_SMALLICON | SHGFI_SYSICONINDEX |  <br />                         SHGFI_USEFILEATTRIBUTES | (bSelected ? SHGFI_OPENICON : 0));<br />            return   sfi.iIcon;<br />           }<br />           return  -1;<br />      }<br /></p><p><br /></p><hr style="WIDTH: 100%; HEIGHT: 2px" /><h3><span style="COLOR: rgb(153,51,0)">22. listctrl内容进行大数据量更新时，避免闪烁</span></h3><p>      m_<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">list</b>.SetRedraw(FALSE);<br />      //更新内容<br />      m_<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">list</b>.SetRedraw(TRUE);<br />      m_<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">list</b>.Invalidate();<br />      m_<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">list</b>.UpdateWindow();<br />  <br />或者参考 <br /></p><p><a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_mfc_cwnd.3a3a.setredraw.asp">http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_mfc_cwnd.3a3a.setredraw.asp</a><br /></p><p><br /></p><hr style="WIDTH: 100%; HEIGHT: 2px" /><h3><span style="COLOR: rgb(153,51,0)">23. listctrl排序 </span></h3><p>Q250614：How To Sort Items in a CListCtrl in Report View<br /><a href="http://support.microsoft.com/kb/250614/en-us">http://support.microsoft.com/kb/250614/en-us</a><br /></p><p><br /></p><hr style="WIDTH: 100%; HEIGHT: 2px" /><h3><span style="COLOR: rgb(153,51,0)">24. 在listctrl中选中某个item时动态改变其icon或bitmap</span></h3>Q141834: How to change the icon or the bitmap of a CListCtrl item in Visual C++<br /><a href="http://support.microsoft.com/kb/141834/en-us">http://support.microsoft.com/kb/141834/en-us</a><br /><br /><br /><hr style="WIDTH: 100%; HEIGHT: 2px" /><h3><span style="COLOR: rgb(153,51,0)">25. 在添加item后，再InsertColumn()后导致整列数据移动的问题</span></h3><p>Q151897: CListCtrl::InsertColumn() Causes Column Data to Shift <br /><a href="http://support.microsoft.com/kb/151897/en-us">http://support.microsoft.com/kb/151897/en-us</a><br /></p><p><br /></p><hr style="WIDTH: 100%; HEIGHT: 2px" /><h3><span style="COLOR: rgb(153,51,0)">26. 关于listctrl第一列始终居左的问题</span></h3><p>解决办法：把第一列当一个虚列，从第二列开始插入列及数据，最后<b style="COLOR: black; BACKGROUND-COLOR: #ff66ff">删除</b>第一列。<br />      <br />具体解释参阅   <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/commctls/listview/structures/lvcolumn.asp">http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/commctls/listview/structures/lvcolumn.asp</a><br /></p><p> </p><hr style="WIDTH: 100%; HEIGHT: 2px" /><h3><span style="COLOR: rgb(153,51,0)">27. 锁定column header的拖动</span></h3><p><a href="http://msdn.microsoft.com/msdnmag/issues/03/06/CQA/">http://msdn.microsoft.com/msdnmag/issues/03/06/CQA/</a><br /></p><p><br /></p><hr style="WIDTH: 100%; HEIGHT: 2px" /><h3 style="COLOR: rgb(153,51,0)">28. 如何隐藏clistctrl的列</h3><p>    把需隐藏的列的宽度设为0,然后检测当该列为隐藏列时，用上面第27点的锁定column 的拖动来实现<br /><br /></p><hr style="WIDTH: 100%; HEIGHT: 2px" /><h3><span style="COLOR: rgb(153,51,0)">29. listctrl进行大数据量操作时，使用virtual <b style="COLOR: black; BACKGROUND-COLOR: #ffff66">list</b> </span>   </h3><p><a href="http://www.microsoft.com/msj/archive/S2061.aspx">http://www.microsoft.com/msj/archive/S2061.aspx</a><br /><a href="http://www.codeguru.com/cpp/controls/listview/advanced/article.php/c4151/">http://www.codeguru.com/cpp/controls/listview/advanced/article.php/c4151/</a><br /><a href="http://www.codeproject.com/listctrl/virtuallist.asp">http://www.codeproject.com/listctrl/virtuallist.asp</a><br /></p><p><br /></p><hr style="WIDTH: 100%; HEIGHT: 2px" /><h3><span style="COLOR: rgb(153,51,0)">30. 关于item只能显示259个字符的问题</span></h3><p>解决办法：需要在item上放一个edit。<br /></p><p><br /></p><hr style="WIDTH: 100%; HEIGHT: 2px" /><h3><span style="COLOR: rgb(153,51,0)">31. 响应在listctrl的column header上的鼠标<b style="COLOR: black; BACKGROUND-COLOR: #99ff99">右键</b>单击</span></h3><p>Q125694: How To Find Out Which Listview Column Was Right-Clicked<br /><a href="http://support.microsoft.com/kb/125694/en-us">http://support.microsoft.com/kb/125694/en-us</a><br /></p><p><br /></p><hr style="WIDTH: 100%; HEIGHT: 2px" /><h3><span style="COLOR: rgb(153,51,0)">32. 类似于windows资源管理器的listview</span></h3><p>Q234310: How to implement a ListView <b style="COLOR: black; BACKGROUND-COLOR: #a0ffff">control</b> that is similar to Windows Explorer by using DirLV.exe<br /><a href="http://support.microsoft.com/kb/234310/en-us">http://support.microsoft.com/kb/234310/en-us</a><br /></p><p> </p><hr style="WIDTH: 100%; HEIGHT: 2px" /><h3 style="COLOR: rgb(153,51,0)">33. 在ListCtrl中OnTimer只响应两次的问题</h3><p>Q200054：<br />PRB: OnTimer() Is Not Called Repeatedly for a <b style="COLOR: black; BACKGROUND-COLOR: #ffff66">List</b><b style="COLOR: black; BACKGROUND-COLOR: #a0ffff">Control</b><br /><a href="http://support.microsoft.com/kb/200054/en-us">http://support.microsoft.com/kb/200054/en-us</a><br /></p><hr style="WIDTH: 100%; HEIGHT: 2px" /><h3><span style="COLOR: rgb(153,51,0)">34. 以下为一些为实现各种自定义功能的listctrl派生类</span></h3><p>          (1)    <span style="COLOR: rgb(153,51,0)">拖放</span>        <br />                   <a href="http://www.codeproject.com/listctrl/dragtest.asp">http://www.codeproject.com/listctrl/dragtest.asp</a></p><p>                   <span style="COLOR: rgb(153,51,0)">在CListCtrl和CTreeCtrl间拖放</span><br />                   <a href="http://support.microsoft.com/kb/148738/en-us">http://support.microsoft.com/kb/148738/en-us</a><br />  <br />          (2)    <span style="COLOR: rgb(153,51,0)">多功能listctrl</span><br />                   支持subitem可编辑，图标，radiobutton，checkbox，字符串改变颜色的类<br />                   <a href="http://www.codeproject.com/listctrl/quicklist.asp">http://www.codeproject.com/listctrl/quicklist.asp</a><br />  <br />                   <span style="COLOR: rgb(153,51,0)">支持排序，subitem可编辑，subitem图标，subitem改变颜色的类</span><br />                   <a href="http://www.codeproject.com/listctrl/ReportControl.asp">http://www.codeproject.com/listctrl/ReportControl.asp</a></p><p>          (3)    <span style="COLOR: rgb(153,51,0)">subitem中显示超链接</span><br />                   <a href="http://www.codeproject.com/listctrl/CListCtrlLink.asp">http://www.codeproject.com/listctrl/CListCtrlLink.asp</a></p><p>          (4)    <span style="COLOR: rgb(153,51,0)">subitem的tooltip提示</span><br />                   <a href="http://www.codeproject.com/listctrl/ctooltiplistctrl.asp">http://www.codeproject.com/listctrl/ctooltiplistctrl.asp</a></p><p>          (5)   <span style="COLOR: rgb(153,51,0)"> subitem中显示进度条</span>    <br />                   <a href="http://www.codeproject.com/listctrl/ProgressListControl.asp">http://www.codeproject.com/listctrl/ProgressListControl.asp</a><br />                   <a href="http://www.codeproject.com/listctrl/napster.asp">http://www.codeproject.com/listctrl/napster.asp</a><br />                   <a href="http://www.codeguru.com/Cpp/controls/listview/article.php/c4187/">http://www.codeguru.com/Cpp/controls/listview/article.php/c4187/</a></p><p>          (6)    <span style="COLOR: rgb(153,51,0)">动态改变subitem的颜色和背景色</span><br />                    <a href="http://www.codeproject.com/listctrl/highlightlistctrl.asp">http://www.codeproject.com/listctrl/highlightlistctrl.asp</a><br />                    <a href="http://www.codeguru.com/Cpp/controls/listbox/colorlistboxes/article.php/c4757/">http://www.codeguru.com/Cpp/controls/listbox/colorlistboxes/article.php/c4757/</a><br /> <br />          (7)    <span style="COLOR: rgb(153,51,0)">类vb属性对话框</span><br />                    <a href="http://www.codeproject.com/listctrl/propertylistctrl.asp">http://www.codeproject.com/listctrl/propertylistctrl.asp</a><br />                    <a href="http://www.codeguru.com/Cpp/controls/listview/propertylists/article.php/c995/">http://www.codeguru.com/Cpp/controls/listview/propertylists/article.php/c995/</a><br />                    <a href="http://www.codeguru.com/Cpp/controls/listview/propertylists/article.php/c1041/">http://www.codeguru.com/Cpp/controls/listview/propertylists/article.php/c1041/</a><br />  <br />          (8)    <span style="COLOR: rgb(153,51,0)">选中subitem(只高亮选中的item)</span><br />                    <a href="http://www.codeproject.com/listctrl/SubItemSel.asp">http://www.codeproject.com/listctrl/SubItemSel.asp</a><br />                    <a href="http://www.codeproject.com/listctrl/ListSubItSel.asp">http://www.codeproject.com/listctrl/ListSubItSel.asp</a><br />  <br />          (9)    <span style="COLOR: rgb(153,51,0)">改变行高</span><br />                    <a href="http://www.codeproject.com/listctrl/changerowheight.asp">http://www.codeproject.com/listctrl/changerowheight.asp</a><br />  <br />          (10)   <span style="COLOR: rgb(153,51,0)">改变行颜色</span><br />                    <a href="http://www.codeproject.com/listctrl/coloredlistctrl.asp">http://www.codeproject.com/listctrl/coloredlistctrl.asp</a><br />  <br />          (11)   <span style="COLOR: rgb(153,51,0)">可编辑subitem的listctrl</span><br />                    <a href="http://www.codeproject.com/listctrl/nirs2000.asp">http://www.codeproject.com/listctrl/nirs2000.asp</a><br />                    <a href="http://www.codeproject.com/listctrl/editing_subitems_in_listcontrol.asp">http://www.codeproject.com/listctrl/editing_subitems_in_listcontrol.asp</a><br />  <br />          (12)   <span style="COLOR: rgb(153,51,0)">subitem可编辑，插入combobox，改变行颜色，subitem的tooltip提示</span><br />                    <a href="http://www.codeproject.com/listctrl/reusablelistcontrol.asp">http://www.codeproject.com/listctrl/reusablelistcontrol.asp</a><br />  <br />          (13)   <span style="COLOR: rgb(153,51,0)">header 中允许多行字符串</span><br />                    <a href="http://www.codeproject.com/listctrl/headerctrlex.asp">http://www.codeproject.com/listctrl/headerctrlex.asp</a><br />  <br />          (14)   <span style="COLOR: rgb(153,51,0)">插入combobox</span><br />                    <a href="http://www.codeguru.com/Cpp/controls/listview/editingitemsandsubitem/article.php/c979/">http://www.codeguru.com/Cpp/controls/listview/editingitemsandsubitem/article.php/c979/</a><br />  <br />          (15)   <span style="COLOR: rgb(153,51,0)">添加背景图片</span><br />                    <a href="http://www.codeguru.com/Cpp/controls/listview/backgroundcolorandimage/article.php/c4173/">http://www.codeguru.com/Cpp/controls/listview/backgroundcolorandimage/article.php/c4173/</a><br />                    <a href="http://www.codeguru.com/Cpp/controls/listview/backgroundcolorandimage/article.php/c983/">http://www.codeguru.com/Cpp/controls/listview/backgroundcolorandimage/article.php/c983/</a><br />                    <a href="http://www.vchelp.net/vchelp/archive.asp?type_id=9&amp;class_id=1&amp;cata_id=1&amp;article_id=1088&amp;search_term">http://www.vchelp.net/vchelp/archive.asp?type_id=9&amp;class_id=1&amp;cata_id=1&amp;article_id=1088&amp;search_term</a>=<br />    <br />          (16)  <span style="COLOR: rgb(153,51,0)">自适应宽度的listctrl</span><br />                    <a href="http://www.codeproject.com/useritems/AutosizeListCtrl.asp">http://www.codeproject.com/useritems/AutosizeListCtrl.asp</a><br /></p><p>          (17)  <span style="COLOR: rgb(153,51,0)">改变ListCtrl高亮时的颜色(默认为蓝色)</span><br />                   处理<code> NM_CUSTOMDRAW <br />           <a href="http://www.codeproject.com/listctrl/lvcustomdraw.asp">http://www.codeproject.com/listctrl/lvcustomdraw.asp</a></code></p><p><code>     (18)  改变header颜色<br />          <a href="http://www.pocketpcdn.com/articles/hdr_color.html">http://www.pocketpcdn.com/articles/hdr_color.html</a><br /><br />35.根据父窗口的大小,自动调整子窗口(list control)的大小<br />在父窗口WM_SIZE响应函数中加入如下代码：   <br />  CRect   layoutRect;   <br />  GetClientRect(&amp;layoutRect);   <br />  if(m_listCtrl.m_hWnd)   <br />  {   <br />  m_listCtrl.SetWindowPos(NULL   <br />  ,   layoutRect.left   <br />  ,   layoutRect.top   <br />  ,   layoutRect.Width()   <br />  ,   layoutRect.Height()   <br />  ,   SWP_SHOWWINDOW);   <br />  }   </code></p><img src ="http://www.cppblog.com/deadpunk/aggbug/19433.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/deadpunk/" target="_blank">活着就是折腾，所以当然要骠悍的折腾</a> 2007-03-08 16:22 <a href="http://www.cppblog.com/deadpunk/archive/2007/03/08/19433.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>获取系统时间并写log,还在主窗口的edit控件中显示出来(本段代码不在主窗口类中)</title><link>http://www.cppblog.com/deadpunk/archive/2007/03/08/19410.html</link><dc:creator>活着就是折腾，所以当然要骠悍的折腾</dc:creator><author>活着就是折腾，所以当然要骠悍的折腾</author><pubDate>Thu, 08 Mar 2007 02:20:00 GMT</pubDate><guid>http://www.cppblog.com/deadpunk/archive/2007/03/08/19410.html</guid><wfw:comment>http://www.cppblog.com/deadpunk/comments/19410.html</wfw:comment><comments>http://www.cppblog.com/deadpunk/archive/2007/03/08/19410.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/deadpunk/comments/commentRss/19410.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/deadpunk/services/trackbacks/19410.html</trackback:ping><description><![CDATA[    m_edtdisplay_called = (CEdit*)(AfxGetMainWnd()-&gt;GetDlgItem(IDC_DISPLAY_CALLED));<br />    std::ofstream logfile;<br /><br /><br />  AfxGetMainWnd()-&gt;UpdateData(TRUE);<br />  CString strDisplay;<br />  m_edtdisplay_called-&gt;GetWindowText(strDisplay);<br />  logfile.open("Log.txt", std::ios::app);<br />  char tmpbuf[128];<br />  _strdate(tmpbuf);  //retrieve the OS date<br />  logfile &lt;&lt; "[" &lt;&lt; tmpbuf &lt;&lt; " ";<br />  strDisplay = strDisplay + "[" + tmpbuf + " ";<br />  _strtime(tmpbuf);  //retrieve the OS time<br />  logfile &lt;&lt; tmpbuf &lt;&lt; "]" &lt;&lt; " AlarmStoreCallback::indexCleared() has been called! " &lt;&lt; std::endl;<br />  strDisplay = strDisplay + tmpbuf + "]" + " AlarmStoreCallback::indexCleared() has been called! " + "\r\n";<br />  m_edtdisplay_called-&gt;SetWindowText(strDisplay);<br />  AfxGetMainWnd()-&gt;UpdateData(TRUE);  //display in the control<br />  logfile &lt;&lt; std::flush;<br />  logfile.close();   <img src ="http://www.cppblog.com/deadpunk/aggbug/19410.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/deadpunk/" target="_blank">活着就是折腾，所以当然要骠悍的折腾</a> 2007-03-08 10:20 <a href="http://www.cppblog.com/deadpunk/archive/2007/03/08/19410.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>