﻿<?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++博客-极品垃圾-文章分类-vc</title><link>http://www.cppblog.com/bestcln/category/8824.html</link><description>初学VC ,就是把每天所看到的整理到博客，慢慢消化这些内容。见证我的学习之路吧。很多都是转载。</description><language>zh-cn</language><lastBuildDate>Tue, 09 Jun 2009 05:24:56 GMT</lastBuildDate><pubDate>Tue, 09 Jun 2009 05:24:56 GMT</pubDate><ttl>60</ttl><item><title>windows消息机制  (1)</title><link>http://www.cppblog.com/bestcln/articles/87137.html</link><dc:creator>极品垃圾</dc:creator><author>极品垃圾</author><pubDate>Tue, 09 Jun 2009 01:19:00 GMT</pubDate><guid>http://www.cppblog.com/bestcln/articles/87137.html</guid><wfw:comment>http://www.cppblog.com/bestcln/comments/87137.html</wfw:comment><comments>http://www.cppblog.com/bestcln/articles/87137.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/bestcln/comments/commentRss/87137.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/bestcln/services/trackbacks/87137.html</trackback:ping><description><![CDATA[<p><strong>1. 窗口过程</strong> <br><br>每个窗口会有一个称为窗口过程的回调函数(WndProc)，它带有四个参数，分别为：窗口句柄(Window Handle),消息ID(Message ID),和两个消息参数(wParam, lParam), 当窗口收到消息时系统就会调用此窗口过程来处理消息。（所以叫回调函数）</p>
<p><strong>2 消息类型</strong> <br><br><strong>1) 系统定义消息(System-Defined Messages)</strong> <br><br>在SDK中事先定义好的消息，非用户定义的，其范围在[0x0000, 0x03ff]之间， 可以分为以下三类：<br><br><strong>1&gt;窗口消息(Windows Message)</strong> <br><br>与窗口的内部运作有关，如创建窗口，绘制窗口，销毁窗口等。可以是一般的窗口，也可以是Dialog,控件等。<br><br>如：WM_CREATE, WM_PAINT, WM_MOUSEMOVE, WM_CTLCOLOR, WM_HSCROLL...<br><br><strong>2&gt;命令消息(Command Message)<br><br></strong>与处理用户请求有关， 如单击菜单项或工具栏或控件时， 就会产生命令消息。<br><br>WM_COMMAND, LOWORD(wParam)表示菜单项，工具栏按钮或控件的ID。如果是控件, HIWORD(wParam)表示控件消息类型<br><br><strong>3&gt; 控件通知(Notify Message)</strong> <br><br>控件通知消息， 这是最灵活的消息格式， 其Message, wParam, lParam分别为：WM_NOTIFY, 控件ID，指向NMHDR的指针。NMHDR包含控件通知的内容， 可以任意扩展。<br><br><strong>2) 程序定义消息(Application-Defined Messages)</strong> <br><br>用户自定义的消息， 对于其范围有如下规定：<br><br>WM_USER: 0x0400-0x7FFF&nbsp;&nbsp;&nbsp; (ex. WM_USER+10)<br><br>WM_APP(winver&gt;4.0): 0x8000-0xBFFF (ex.WM_APP+4)<br><br>RegisterWindowMessage: 0xC000-0xFFFF</p>
<p><strong>3 消息队列(Message Queues)</strong> <br><br>Windows中有两种类型的消息队列<br><br><strong>1) 系统消息队列(System Message Queue)<br><br></strong>这是一个系统唯一的Queue，设备驱动(mouse, keyboard)会把操作输入转化成消息存在系统队列中，然后系统会把此消息放到目标窗口所在的线程的消息队列(thread-specific message queue)中等待处理<br><br><strong>2) 线程消息队列(Thread-specific Message Queue)<br><br></strong>每一个GUI线程都会维护这样一个线程消息队列。(这个队列只有在线程调用GDI函数时才会创建，默认不创建)。然后线程消息队列中的消息会被送到相应的窗口过程(WndProc)处理.<br><br>注意： 线程消息队列中WM_PAINT，WM_TIMER只有在Queue中没有其他消息的时候才会被处理，WM_PAINT消息还会被合并以提高效率。其他所有消息以先进先出（FIFO）的方式被处理。</p>
<p><strong>4 队列消息(Queued Messages)和非队列消息(Non-Queued Messages)<br><br>1)队列消息(Queued Messages)</strong> <br><br>消息会先保存在消息队列中，消息循环会从此队列中取消息并分发到各窗口处理<br><br>如鼠标，键盘消息。<br><br><strong>2) 非队列消息(NonQueued Messages)<br><br></strong>消息会绕过系统消息队列和线程消息队列直接发送到窗口过程被处理<br><br>如： WM_ACTIVATE, WM_SETFOCUS, WM_SETCURSOR， WM_WINDOWPOSCHANGED <br><br>注意: postMessage发送的消息是队列消息，它会把消息Post到消息队列中； SendMessage发送的消息是非队列消息， 被直接送到窗口过程处理</p>
<p><strong>5 PostMessage(PostThreadMessage), SendMessage</strong> <br><br>PostMessage:把消息放到指定窗口所在的线程消息队列中后立即返回。 PostThreadMessage：把消息放到指定线程的消息队列中后立即返回。<br><br>SendMessage：直接把消息送到窗口过程处理， 处理完了才返回。</p>
<p><strong>6 GetMessage, PeekMessage</strong> <br><br>PeekMessage会立即返回&nbsp;&nbsp;可以保留消息<br><br>GetMessage在有消息时返回&nbsp;会删除消息</p>
<p><strong>7 TranslateMessage, TranslateAccelerator</strong> <br><br>TranslateMessage: 把一个virtual-key消息转化成字符消息(character message)，并放到当前线程的消息队列中，消息循环下一次取出处理。<br><br>TranslateAccelerator: 将快捷键对应到相应的菜单命令。它会把WM_KEYDOWN 或 WM_SYSKEYDOWN转化成快捷键表中相应的WM_COMMAND 或WM_SYSCOMMAND消息， 然后把转化后的 WM_COMMAND或WM_SYSCOMMAND直接发送到窗口过程处理， 处理完后才会返回。</p>
<p><strong>8(消息死锁( Message Deadlocks)</strong> <br><br>假设有线程A和B， 现在有以下下步骤<br><br>1) 线程A SendMessage给线程B, A等待消息在线程B中处理后返回<br><br>2) 线程B收到了线程A发来的消息，并进行处理， 在处理过程中，B也向线程A SendMessgae，然后等待从A返回。<br><br>因为此时， 线程A正等待从线程B返回， 无法处理B发来的消息， 从而导致了线程A,B相互等待， 形成死锁。多个线程也可以形成环形死锁。<br><br>可以使用 SendNotifyMessage或SendMessageTimeout来避免出现死锁。</p>
<p><strong>9 BroadcastSystemMessage</strong> <br><br>我们一般所接触到的消息都是发送给窗口的， 其实， 消息的接收者可以是多种多样的，它可以是应用程序(applications), 可安装驱动(installable drivers), 网络设备(network drivers), 系统级设备驱动(system-level device drivers)等， <br><br>BroadcastSystemMessage这个API可以对以上系统组件发送消息</p>
<img src ="http://www.cppblog.com/bestcln/aggbug/87137.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/bestcln/" target="_blank">极品垃圾</a> 2009-06-09 09:19 <a href="http://www.cppblog.com/bestcln/articles/87137.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>匈牙利表示法</title><link>http://www.cppblog.com/bestcln/articles/86625.html</link><dc:creator>极品垃圾</dc:creator><author>极品垃圾</author><pubDate>Wed, 03 Jun 2009 01:45:00 GMT</pubDate><guid>http://www.cppblog.com/bestcln/articles/86625.html</guid><wfw:comment>http://www.cppblog.com/bestcln/comments/86625.html</wfw:comment><comments>http://www.cppblog.com/bestcln/articles/86625.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/bestcln/comments/commentRss/86625.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/bestcln/services/trackbacks/86625.html</trackback:ping><description><![CDATA[<p>几年以前,Charles Simonyi(他后来成为微软的著名程序员)设计了一种以前缀为基础的命名方法,这种方法后来称为"匈牙利表示法"以记念他.他的思想是根据每个标识符所代表的含义给它一个前缀.微软后来采用了这个思想,给每个标识符一个前缀以说明它的数据类型.因此,整型变量的前缀是n,长整型变量是nl,字符型数组变量是ca,以及字符串(以空类型结尾的字符数组)以sz为前缀.这些名字可能会非常古怪.比如说:lpszFoo表示"Foo"是一个指向以空字符为结尾的字符串的长整型指针.</p>
<p>&nbsp;</p>
<p>这种方法的优点是使人能够通过变量的名字来辨别变量的类型,而不比去查找它的定义.遗憾的是,这种方法不仅使变量名字非常绕口,而且使改变变量类型的工作变得十分艰巨.在Windows3.1中,整型变量为16为宽.如果我们在开始时采用了一个整型变量,但是在通过30---40个函数的计算之后,发现采用整型变量宽度不够,这时我们不仅要改变这个变量的类型,而且要改变这个变量在这30--40个函数中的名字.</p>
<p>&nbsp;</p>
<p>因为不切实际,除了一些顽固的Windows程序员外已经没有人再使用"匈牙利表示法"了.毫无疑问,在某种场合它依然存在,但大部分人现在已经抛弃它了.一般而言,输入前缀是一种糟糕的想法,因为它把变量于其类型紧紧地绑在了一起.</p>
<p>对于30行以下的函数，匈牙利方法一般有优势。</p>
<p>尤其是对界面编程，有优势。</p>
<p>但对于有强烈的算法要求、尤其是有很多抽象类型的C++程序，匈牙利方法简直是一个灾难。</p>
<p>看你用在什么地方。</p>
<p>现在有了很好的IDE工具,如:VC,SourceInsight等.</p>
<p>选中变量,会自动提示告诉你它的声明和定义,这样</p>
<p>匈牙利命名法就没有很大的必要了.</p>
<p>无非就是为了程序可读性较好.</p>
<p>实际上良好的代码书写习惯比强制使用匈牙利命名法更重要.</p>
<p>系统性。整体性。可读性。分类要清楚。要有注释！</p>
<p>&nbsp;</p>
<p>匈牙利命名法是微软推广的一种关于变量、函数、对象、前缀、宏定义等各种类型的符号的命名规范。匈牙利命名法的主要思想是：在变量和函数名中加入前缀以增进人们对程序的理解。它是由微软内部的一个匈牙利人发起使用的，结果它在微软内部逐渐流行起来，并且推广给了全世界的Windows开发人员。下面将介绍匈牙利命名法，后面的例子里也会尽量遵守它和上面的代码风格。还是那句话，并不是要求所有的读者都要去遵守，但是希望读者作为一个现代的软件开发人员都去遵守它。</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Array&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 数组</p>
<p>&nbsp; b&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BOOL (int)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 布尔(整数)</p>
<p>&nbsp; by&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Unsigned Char (Byte)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 无符号字符(字节)</p>
<p>&nbsp; c&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Char&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 字符(字节)</p>
<p>&nbsp; cb&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Count of bytes&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 字节数</p>
<p>&nbsp; cr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Color reference value&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 颜色(参考)值</p>
<p>&nbsp; cx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Count of x (Short)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; x的集合(短整数)</p>
<p>&nbsp; dw&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DWORD&nbsp;&nbsp; (unsigned long)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 双字(无符号长整数)</p>
<p>&nbsp; f&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Flags&nbsp;&nbsp; (usually multiple bit values)&nbsp;&nbsp; 标志(一般是有多位的数值)</p>
<p>&nbsp; fn&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Function&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 函数</p>
<p>&nbsp; g_&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; global&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 全局的</p>
<p>&nbsp; h&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Handle&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 句柄</p>
<p>&nbsp; i&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Integer&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 整数</p>
<p>&nbsp; l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Long&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 长整数</p>
<p>&nbsp; lp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Long pointer&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 长指针</p>
<p>&nbsp; m_&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Data member of a class&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 一个类的数据成员</p>
<p>&nbsp; n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Short int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 短整数</p>
<p>&nbsp; p&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Pointer&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 指针</p>
<p>&nbsp; s&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 字符串</p>
<p>&nbsp; sz&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Zero terminated String&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 以0结尾的字符串</p>
<p>&nbsp; tm&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Text metric&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 文本规则</p>
<p>&nbsp; u&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Unsigned int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 无符号整数</p>
<p>&nbsp; ul&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Unsigned long (ULONG)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 无符号长整数</p>
<p>&nbsp; w&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WORD (unsigned short)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 无符号短整数</p>
<p>&nbsp; x,y&nbsp;&nbsp;&nbsp;&nbsp; x, y coordinates (short)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 坐标值/短整数</p>
<p>&nbsp; v&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 空</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>有关项目的全局变量用g_开始，类成员变量用m_，局部变量若函数较大则可考虑用l_用以显示说明其是局部变量。</p>
<p>&nbsp;</p>
<p>前缀&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 类型&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 例子</p>
<p>g_&nbsp;&nbsp;&nbsp; 全局变量&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; g_Servers</p>
<p>C&nbsp;&nbsp;&nbsp;&nbsp; 类或者结构体&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CDocument，CPrintInfo</p>
<p>m_&nbsp;&nbsp; 成员变量&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_pDoc，m_nCustomers</p>
<p>&nbsp;</p>
<p>VC常用前缀列表：</p>
<p>&nbsp;</p>
<p>前缀&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 类型&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 描述&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 例子</p>
<p>ch&nbsp;&nbsp;&nbsp; char 8位字符&nbsp;&nbsp;&nbsp; chGrade</p>
<p>ch&nbsp;&nbsp;&nbsp; TCHAR&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 16位UNICODE类型字符&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; chName</p>
<p>b&nbsp;&nbsp;&nbsp;&nbsp; BOOL&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 布尔变量&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bEnabled</p>
<p>n&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp; 整型（其大小由操作系统决定）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nLength</p>
<p>n&nbsp;&nbsp;&nbsp;&nbsp; UINT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 无符号整型（其大小由操作系统决定）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nLength</p>
<p>w&nbsp;&nbsp;&nbsp; WORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 16位无符号整型&nbsp;&nbsp;&nbsp; wPos</p>
<p>l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LONG&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 32位有符号整型&nbsp;&nbsp;&nbsp; lOffset</p>
<p>dw&nbsp;&nbsp; DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 32位无符号整型&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dwRange</p>
<p>p&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Ambient memory model pointer 内存模块指针，指针变量&nbsp;&nbsp;&nbsp; pDoc</p>
<p>lp&nbsp;&nbsp;&nbsp;&nbsp; FAR*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 长指针&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lpDoc</p>
<p>lpsz&nbsp; LPSTR&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 32位字符串指针&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lpszName</p>
<p>lpsz&nbsp; LPCSTR&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 32位常量字符串指针&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lpszName</p>
<p>lpsz&nbsp; LPCTSTR&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 32位UNICODE类型常量指针&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lpszName</p>
<p>h&nbsp;&nbsp;&nbsp;&nbsp; handle&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Windows对象句柄&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hWnd</p>
<p>lpfn&nbsp; (*fn)()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 回调函数指针 Callback Far pointer to CALLBACK function&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lpfnAbort</p>
<p>&nbsp;</p>
<p>Windows对象名称缩写：</p>
<p>&nbsp;</p>
<p>Windows对象&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 例子变量&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MFC类&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 例子对象</p>
<p>HWND&nbsp;&nbsp;&nbsp; hWnd;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CWnd*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pWnd;</p>
<p>HDLG&nbsp;&nbsp;&nbsp;&nbsp; hDlg;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CDialog*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pDlg;</p>
<p>HDC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hDC;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CDC*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pDC;</p>
<p>HGDIOBJ&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hGdiObj;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CGdiObject*&nbsp;&nbsp;&nbsp;&nbsp; pGdiObj;</p>
<p>HPEN&nbsp;&nbsp;&nbsp;&nbsp; hPen;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CPen*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pPen; </p>
<p>HBRUSH hBrush;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CBrush*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pBrush; </p>
<p>HFONT&nbsp;&nbsp; hFont;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CFont*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pFont; </p>
<p>HBITMAP&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hBitmap;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CBitmap*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pBitmap; </p>
<p>HPALETTE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hPalette;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CPalette*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pPalette; </p>
<p>HRGN&nbsp;&nbsp;&nbsp;&nbsp; hRgn;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CRgn*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pRgn; </p>
<p>HMENU hMenu;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CMenu*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pMenu; </p>
<p>HWND&nbsp;&nbsp;&nbsp; hCtl;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CStatic*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pStatic; </p>
<p>HWND&nbsp;&nbsp;&nbsp; hCtl;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CButton*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pBtn;</p>
<p>HWND&nbsp;&nbsp;&nbsp; hCtl;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CEdit*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pEdit; </p>
<p>HWND&nbsp;&nbsp;&nbsp; hCtl;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CListBox*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pListBox;</p>
<p>HWND&nbsp;&nbsp;&nbsp; hCtl;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CComboBox*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pComboBox;</p>
<img src ="http://www.cppblog.com/bestcln/aggbug/86625.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/bestcln/" target="_blank">极品垃圾</a> 2009-06-03 09:45 <a href="http://www.cppblog.com/bestcln/articles/86625.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>双缓存   （2）</title><link>http://www.cppblog.com/bestcln/articles/85679.html</link><dc:creator>极品垃圾</dc:creator><author>极品垃圾</author><pubDate>Mon, 25 May 2009 02:43:00 GMT</pubDate><guid>http://www.cppblog.com/bestcln/articles/85679.html</guid><wfw:comment>http://www.cppblog.com/bestcln/comments/85679.html</wfw:comment><comments>http://www.cppblog.com/bestcln/articles/85679.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/bestcln/comments/commentRss/85679.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/bestcln/services/trackbacks/85679.html</trackback:ping><description><![CDATA[显示的图形为什么会闪烁<br>　　我们的绘图过程大多放在OnDraw或者OnPaint函数中，OnDraw在进行屏幕显示时是由OnPaint进行调用的。当窗口由于任何原因需要重绘时，总是先用背景色将显示区清除，然后才调用OnPaint，而背景色往往与绘图内容反差很大，这样在短时间内背景色与显示图形的交替出现，使得显示窗口看起来在闪。如果将背景刷设置成NULL，这样无论怎样重绘图形都不会闪了。当然，这样做会使得窗口的显示乱成一团，因为重绘时没有背景色对原来绘制的图形进行清除，而又叠加上了新的图形。有的人会说，闪烁是因为绘图的速度太慢或者显示的图形太复杂造成的，其实这样说并不对，绘图的显示速度对闪烁的影响不是根本性的。例如在OnDraw(CDC *pDC)中这样写：<br><br>　pDC-&gt;MoveTo(0,0);<br>　pDC-&gt;LineTo(100,100);<br><br>　　这个绘图过程应该是非常简单、非常快了吧，但是拉动窗口变化时还是会看见闪烁。其实从道理上讲，画图的过程越复杂越慢闪烁应该越少，因为绘图用的时间与用背景清除屏幕所花的时间的比例越大人对闪烁的感觉会越不明显。比如：清楚屏幕时间为1s绘图时间也是为1s，这样在10s内的连续重画中就要闪烁5次；如果清楚屏幕时间为1s不变，而绘图时间为9s，这样10s内的连续重画只会闪烁一次。这个也可以试验，在OnDraw(CDC *pDC)中这样写：<br><br>for(int i=0;i&lt;100000;i++)<br>{<br>　pDC-&gt;MoveTo(0,i);<br>　pDC-&gt;LineTo(1000,i);<br>}<br><br>　　程序有点极端，但是能说明问题。<br><br>　　说到这里可能又有人要说了，为什么一个简单图形看起来没有复杂图形那么闪呢？这是因为复杂图形占的面积大，重画时造成的反差比较大，所以感觉上要闪得厉害一些，但是闪烁频率要低。那为什么动画的重画频率高，而看起来却不闪？这里，我就要再次强调了，闪烁是什么？闪烁就是反差，反差越大，闪烁越厉害。因为动画的连续两个帧之间的差异很小所以看起来不闪。如果不信，可以在动画的每一帧中间加一张纯白的帧，不闪才怪呢。
<p><font color=#0000ff>2、解决办法：</font><br>　　在图形图象处理编程过程中,双缓冲是一种基本的技术。我们知道,如果窗体在响应WM_PAINT消息的时候要进行复杂的图形处理，那么窗体在重绘时由于过频的刷新而引起闪烁现象。解决这一问题的有效方法就是双缓冲技术。</p>
<p>　　因为窗体在刷新时，总要有一个擦除原来图象的过程OnEraseBkgnd，它利用背景色填充窗体绘图区，然后在调用新的绘图代码进行重绘，这样一擦一写造成了图象颜色的反差。当WM_PAINT的响应很频繁的时候，这种反差也就越发明显。于是我们就看到了闪烁现象。</p>
<p>　　我们会很自然的想到，<font color=#0000ff>避免背景色的填充是最直接的办法。但是那样的话，窗体上会变的一团糟。因为每次绘制图象的时候都没有将原来的图象清除，造成了图象的残留，于是窗体重绘时，画面往往会变的乱七八糟。所以单纯的禁止背景重绘是不够的</font>。我们还要进行重新绘图，但要求速度很快，于是我们想到了使用<font color=#ff0000>BitBlt函数。它可以支持图形块的复制，速度很快。我们可以先在内存中作图，然后用此函数将做好的图复制到前台，同时禁止背景刷新，这样就消除了闪烁</font>。以上也就是双缓冲绘图的基本的思路。</p>
<p><font color=#0000ff>３、具体步骤：<br></font><font color=#0000ff><font color=#000000>　　假设我们建立了一个Draw的工程，我们要在DrawView中进行绘图操作。<br><br>　　在双缓冲方法中，首先要做的是屏蔽背景刷新。背景刷新其实是在响应WM_ERASEBKGND消息。我们在视类（CDrawView）中添加对这个消息的响应，可以看到缺省的代码如下：</font></font></p>
<p>　BOOL CDrawView::OnEraseBkgnd(CDC* pDC) <br>　{<br>&nbsp;&nbsp;&nbsp;&nbsp; 　 //return CDrawView::OnEraseBkgnd(pDC);<br>　　<font color=#0000ff>return TRUE;<br></font>　}<br><br><font color=#0000ff>接下来是双缓冲的实现步骤：<br></font><br><font color=#0000ff>（1）增加成员变量</font>（在DrawView.h文件中）<br><br>　//参数声明<br>　　CBitmap* m_pOldBitmap;<br>　　 CBitmap* m_pMemBitmap; //声明内存中承载临时图象的位图<br>　　CDC* m_pMemDC;&nbsp;&nbsp; //声明用于缓冲作图的内存DC<br><br><font color=#0000ff>（2）初始化变量</font>（在DrawView的构造函数中）<br><br>　　m_pMemDC=new CDC();<br>　　m_pMemBitmap=new CBitmap();<br><br><font color=#0000ff>（3）增加消息响应函数</font><font color=#0080ff>WM_CREATE（<font color=#000000>在DrawView.cpp中</font>）<br><br></font>　int CDrawView::OnCreate(LPCREATESTRUCT lpCreateStruct)<br>　{<br>　　 if (CView::OnCreate(lpCreateStruct) == -1)<br>　　　 return -1;</p>
<p><font color=#0000ff><font color=#000000>　　 int x=GetSystemMetrics(SM_CXSCREEN);<br>　　 int y=GetSystemMetrics(SM_CYSCREEN);<br><br>　　CDC* pDC=GetDC();<br>　　m_pMemDC-&gt;CreateCompatibleDC(pDC); //依附窗口DC创建兼容内存DC<br>　　m_pMemBitmap-&gt;CreateCompatibleBitmap(pDC,x,y); //创建兼容位图<br>　 　m_pOldBitmap=m_pMemDC-&gt;SelectObject(m_pMemBitmap); //将位图选进内存DC,原位图保存到m_pOldBitmap<br><br>　　 CBrush brush(RGB(255,255,255));<br>　　m_pMemDC-&gt;FillRect(CRect(0,0,x,y),&amp;brush);&nbsp;&nbsp;&nbsp; //设置客户区背景为白色<br><br>　　ReleaseDC(pDC);</font></font></p>
<p><font color=#0000ff><font color=#000000>　　return 0;<br>　}<br><font color=#0000ff>（4）修改OnDraw()函数</font>(DrawView.cpp中)<br><br>　　void CDrawView::OnDraw(CDC* pDC)<br>　　{<br>　　　CDocument* pDoc = GetDocument();<br>　　　CRect rc;<br>　　　GetClientRect(&amp;rc);<br>　　　<font color=#0000ff>DrawSomething();&nbsp;&nbsp; //在这个函数里你可以画你想画的东西</font><br>　　　pDC-&gt;BitBlt(0,0,rc.Width(),rc.Height(),m_pMemDC,0,0,SRCCOPY);<br>　　　　//这里就是将内存里面的画布复制到显示设备的buffer了<br></font></font><font color=#0000ff><font color=#000000>　　}<br><br><font color=#0000ff>（5）自己的绘图函数</font>(DrawView.cpp中)<br><br>　　void DrawSomething()<br>　　{<br>&nbsp;&nbsp;&nbsp; 　　m_pMemDC-&gt;Rectangle(0,0,100,100);&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //此处画了个矩形<br>&nbsp;&nbsp;&nbsp; 　　 Invalidate();<br>　　}<br><br><font color=#0000ff>（6）delete掉new的东西</font>（在DrawView的析构函数中）<br><br></font></font><font color=#0000ff><font color=#000000>　　delete m_pBitmap;<br>&nbsp;&nbsp;&nbsp; 　delete m_pMemDC;<br></font></font></p>
<img src ="http://www.cppblog.com/bestcln/aggbug/85679.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/bestcln/" target="_blank">极品垃圾</a> 2009-05-25 10:43 <a href="http://www.cppblog.com/bestcln/articles/85679.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>VC++双缓冲实现方法 </title><link>http://www.cppblog.com/bestcln/articles/85673.html</link><dc:creator>极品垃圾</dc:creator><author>极品垃圾</author><pubDate>Mon, 25 May 2009 01:58:00 GMT</pubDate><guid>http://www.cppblog.com/bestcln/articles/85673.html</guid><wfw:comment>http://www.cppblog.com/bestcln/comments/85673.html</wfw:comment><comments>http://www.cppblog.com/bestcln/articles/85673.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/bestcln/comments/commentRss/85673.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/bestcln/services/trackbacks/85673.html</trackback:ping><description><![CDATA[在图形图象处理编程过程中,双缓冲是一种基本的技术。我们知道,如果窗体在响应WM_PAINT消息的时候要进行复杂的图形处理，那么窗体在重绘时由于过频的刷新而引起闪烁现象。解决这一问题的有效方法就是双缓冲技术。
<p>　　因为窗体在刷新时，总要有一个擦除原来图象的过程OnEraseBkgnd，它利用背景色填充窗体绘图区，然后在调用新的绘图代码进行重绘，这样一擦一写造成了图象颜色的反差。当WM_PAINT的响应很频繁的时候，这种反差也就越发明显。于是我们就看到了闪烁现象。</p>
<p>　　我们会很自然的想到，避免背景色的填充是最直接的办法。但是那样的话，窗体上会变的一团糟。因为每次绘制图象的时候都没有将原来的图象清除，造成了图象的残留，于是窗体重绘时，画面往往会变的乱七八糟。所以单纯的禁止背景重绘是不够的。我们还要进行重新绘图，但要求速度很快，于是我们想到了使用BitBlt函数。它可以支持图形块的复制，速度很快。我们可以先在内存中作图，然后用此函数将做好的图复制到前台，同时禁止背景刷新，这样就消除了闪烁。以上也就是双缓冲绘图的基本的思路。</p>
<p>　　先按普通做图的方法进行编程。即在视类的OnDraw函数中添加绘图代码。在此我们绘制若干同心圆，代码如下：<br>&nbsp;CBCDoc*&nbsp;pDoc&nbsp;=&nbsp;GetDocument();<br>&nbsp;ASSERT_VALID(pDoc);<br>&nbsp;CPoint&nbsp;ptCenter;<br>&nbsp;CRect&nbsp;rect,ellipseRect;<br>&nbsp;GetClientRect(&amp;rect);<br>&nbsp;ptCenter&nbsp;=&nbsp;rect.CenterPoint();<br>&nbsp;for(int&nbsp;i=20;i&gt;0;i--)<br>&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ellipseRect.SetRect(ptCenter,ptCenter);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ellipseRect.InflateRect(i*10,i*10);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pDC-&gt;Ellipse(ellipseRect);<br>&nbsp;}</p>
<p>编译运行程序，尝试改变窗口大小，可以发现闪烁现象。</p>
<p>　　在双缓冲方法中，首先要做的是屏蔽背景刷新。背景刷新其实是在响应WM_ERASEBKGND消息。我们在视类中添加对这个消息的响应，可以看到缺省的代码如下：</p>
<p>BOOL&nbsp;CMYView::OnEraseBkgnd(CDC*&nbsp;pDC)&nbsp;<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;CView::OnEraseBkgnd(pDC);<br>}</p>
<p>是调用父类的OnEraseBkgnd函数，我们屏蔽此调用，只须直接return&nbsp;TRUE;即可。</p>
<p>　　下面是内存缓冲作图的步骤。</p>
<p>&nbsp;CPoint&nbsp;ptCenter;<br>&nbsp;CRect&nbsp;rect,ellipseRect;<br>&nbsp;GetClientRect(&amp;rect);<br>&nbsp;ptCenter&nbsp;=&nbsp;rect.CenterPoint();<br>&nbsp;CDC&nbsp;dcMem;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//用于缓冲作图的内存DC<br>&nbsp;CBitmap&nbsp;bmp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//内存中承载临时图象的位图<br>&nbsp;dcMem.CreateCompatibleDC(pDC);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//依附窗口DC创建兼容内存DC<br>&nbsp;bmp.CreateCompatibleBitmap(&amp;dcMem,rect.Width(),rect.Height());//创建兼容位图<br>&nbsp;dcMem.SelectObject(&amp;bmp);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//将位图选择进内存DC<br>&nbsp;dcMem.FillSolidRect(rect,pDC-&gt;GetBkColor());//按原来背景填充客户区，不然会是黑色<br>&nbsp;for(int&nbsp;i=20;i&gt;0;i--)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//在内存DC上做同样的同心圆图象<br>&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ellipseRect.SetRect(ptCenter,ptCenter);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ellipseRect.InflateRect(i*10,i*10);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dcMem.Ellipse(ellipseRect);<br>&nbsp;}<br>&nbsp;pDC-&gt;BitBlt(0,0,rect.Width(),rect.Height(),&amp;dcMem,0,0,SRCCOPY);//将内存DC上的图象拷贝到前台<br>&nbsp;dcMem.DeleteDC();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//删除DC<br>&nbsp;bm.DeleteObject();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//删除位图</p>
<p>由于复杂的画图操作转入后台，我们看到的是速度很快的复制操作，自然也就消除了闪烁现象。</p>
<img src ="http://www.cppblog.com/bestcln/aggbug/85673.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/bestcln/" target="_blank">极品垃圾</a> 2009-05-25 09:58 <a href="http://www.cppblog.com/bestcln/articles/85673.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>VC++完成Win2000下直接读写磁盘扇区 </title><link>http://www.cppblog.com/bestcln/articles/83612.html</link><dc:creator>极品垃圾</dc:creator><author>极品垃圾</author><pubDate>Thu, 21 May 2009 14:19:00 GMT</pubDate><guid>http://www.cppblog.com/bestcln/articles/83612.html</guid><wfw:comment>http://www.cppblog.com/bestcln/comments/83612.html</wfw:comment><comments>http://www.cppblog.com/bestcln/articles/83612.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/bestcln/comments/commentRss/83612.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/bestcln/services/trackbacks/83612.html</trackback:ping><description><![CDATA[由于Windows 操作系统在很大程度上采取了访问安全保护机制（例如，在Windows操作系统下不能直接访问物理内存、不能使用各种DOS、BIOS中断等等），使得广大程序设计人员在长时间的开发过程中不知不觉地逐渐养成了这样的潜意识——在Windows操作系统下直接操纵硬件设备是极端困难和非常烦琐的，并将其看作Windows编程的一个禁区。尽管在大多数场合下这样的论断还算是贴切，但也并非对所有的硬件设备访问都那么困难。其实Windows在采取&#8220;实保护&#8221;措施的同时也提供了另外的一种有别于在DOS下访问硬件设备的方法，即把所有的硬件设备全部看做&#8220;文件&#8221;，并允许按照对文件的读写方式来对其进行数据存取访问。撰写本文的另外一个目的也就是帮助读者打消在Windows环境下对硬件编程的恐惧心理。<br><br><strong>对磁盘扇区数据的访问</strong><br><br>前面已经提过，在Windows 下把所有的设备当作文件进行操作。如果对串口进行编程或许不少读者还比较熟悉：对于串行端口1、2，可以用&#8221;COM1&#8221;、&#8221;COM2&#8221;作为参数调用CreateFile（）函数，这里的&#8221;COM1&#8221;、&#8221;COM2&#8221;即以文件存放路径的方式指出了要操作的硬件设备。但是如果需要对磁盘的某个扇区进行读写，可能不少读者不会想到使用CreateFile（）函数或是不知如何使用。其实，与对串行端口的访问类似，需要用与文件存放路径相类似的方式指出要操作的硬件设备（硬盘）。但是这里并不是用&#8220;DISK1&#8221;、&#8220;DISK2&#8221;等去标识某一块物理存在的硬盘。由于逻辑扇区是存在于逻辑分区上的，因此这里需要以某种特定的格式来指定需要访问的磁盘逻辑分区。对于逻辑分区X，其格式为&#8221;\\.\X:&#8221;。<br><br>
<table borderColor=#ffcc66 width="90%" align=center border=1>
    <tbody>
        <tr>
            <td>HANDLE CreateFile( LPCTSTR lpFileName, <br><br>DWORD dwDesiredAccess, <br><br>DWORD dwShareMode, <br><br>LPSECURITY_ATTRIBUTES lpSecurityAttributes, <br><br>DWORD dwCreationDisposition, <br><br>DWORD dwFlagsAndAttributes, <br><br>HANDLE hTemplateFile );</td>
        </tr>
    </tbody>
</table>
<br><br>CreateFile（）函数原型如上所示，由于访问的是事实上已经存在的磁盘扇区，因此只能以OPEN_EXISTING标志设置dwCreationDisposition参数指出将要打开已经存在的文件（设备）。至于其他参数的使用与操作普通文件时的用法相同。<br><br>通过CreateFile（）打开的是整个磁盘逻辑分区，而要操作的是该分区的某些扇区，因此还要通过SetFilePointer（）函数以文件操作的方式把指针移到要操作的磁盘扇区开始处。SetFilePointer（）函数原型为：<br><br>
<table borderColor=#ffcc66 width="90%" align=center border=1>
    <tbody>
        <tr>
            <td>DWORD SetFilePointer(HANDLE hFile, <br><br>LONG lDistanceToMove, <br><br>PLONG lpDistanceToMoveHigh,<br><br>DWORD dwMoveMethod);</td>
        </tr>
    </tbody>
</table>
<br><br>参数hFile为CreateFile（）返回的文件（设备）句柄；lDistanceToMove和lpDistanceToMoveHigh指出了要设置偏移量的低端和高端部分；dwMoveMethod指出文件指针从何处开始移动，可能的选项有FILE_START（从文件开始）、FILE_END（从文件结尾）和FILE_CURRENT（从文件当前位置）。<br><br>在定位到要访问的扇区开始位置后就可以通过ReadFile（）或WriteFile（）函数实施相应的读写访问了，具体操作与文件读写并没有什么太大的差别。最后，在完成访问操作后以CloseHandle（）关闭文件句柄释放资源，从而完成一次完整的磁盘扇区数据访问操作。下面给出具体的读、写处理过程：<br><br>
<table borderColor=#ffcc66 width="90%" align=center border=1>
    <tbody>
        <tr>
            <td>BOOL CDirectAccessHDDlg::WriteSectors(BYTE bDrive, DWORD dwStartSector, WORD wSectors, LPBYTE lpSectBuff) <br><br>// 对磁盘扇区数据的写入<br><br>{<br><br>　if (bDrive == 0) return 0;<br><br>　char devName[] = "\\\\.\\A:";<br><br>　devName[4] ='A' + bDrive - 1;<br><br>　HANDLE hDev = CreateFile(devName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);<br><br>　if (hDev == INVALID_HANDLE_VALUE) return 0;<br><br>　SetFilePointer(hDev, 512 * dwStartSector, 0, FILE_BEGIN);<br><br>　DWORD dwCB;<br><br>　BOOL bRet = WriteFile(hDev, lpSectBuff, 512 * wSectors, &amp;dwCB, NULL);<br><br>　CloseHandle(hDev);<br><br>　return bRet;<br><br>}<br><br>BOOL CDirectAccessHDDlg::ReadSectors(BYTE bDrive, DWORD dwStartSector, WORD wSectors, LPBYTE lpSectBuff)<br><br>// 对磁盘扇区数据的读取<br><br>{<br><br>　if (bDrive == 0) return 0;<br><br>　char devName[] = "\\\\.\\A:";<br><br>　devName[4] ='A' + bDrive - 1;<br><br>　HANDLE hDev = CreateFile(devName, GENERIC_READ, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);<br><br>　if (hDev == INVALID_HANDLE_VALUE) return 0;<br><br>　SetFilePointer(hDev, 512 * dwStartSector, 0, FILE_BEGIN);<br><br>　DWORD dwCB;<br><br>　BOOL bRet = ReadFile(hDev, lpSectBuff, 512 * wSectors, &amp;dwCB, NULL);<br><br>　CloseHandle(hDev);<br><br>　return bRet;<br><br>}</td>
        </tr>
    </tbody>
</table>
<br><br><strong>磁盘扇区数据直接读写技术的应用<br><br></strong>上一步实现了对磁盘扇区数据进行读写访问的核心处理过程。在此基础上可以完成一些有实用价值的应用，例如，可以实现对指定磁盘分区中指定起止扇区的内容查看： <br><br>
<table borderColor=#ffcc66 width="90%" align=center border=1>
    <tbody>
        <tr>
            <td>if (ReadSectors(uDiskID, m_uFrom, (UINT)dwSectorNum, bBuf) == FALSE) {<br><br>　MessageBox("所选磁盘分区不存在！", "错误", MB_OK | MB_IConERROR);<br><br>　return;<br><br>}</td>
        </tr>
    </tbody>
</table>
<br><br>为了方便数据的显示，可做如下处理以完成格式转换等工作：<br><br>
<table borderColor=#ffcc66 width="90%" align=center border=1>
    <tbody>
        <tr>
            <td>for (DWORD i = 0; i &lt; dwSectorNum * 512; i++) {<br><br>　sprintf(cBuf, "%s%02X ", cBuf, bBuf[i]);<br><br>　if ((i % 512) == 511)<br><br>sprintf(cBuf, "%s\r\n第%d扇区\r\n", cBuf, (int)(i / 512) + m_uFrom);<br><br>　if ((i % 16) == 15)<br><br>sprintf(cBuf, "%s\r\n", cBuf);<br><br>　else if ((i % 16) == 7)<br><br>sprintf(cBuf, "%s- ", cBuf);<br><br>}</td>
        </tr>
    </tbody>
</table>
<br><br>
<table width="90%" align=center border=0>
    <tbody>
        <tr>
            <td><img onerror="this.src='/Program/image/200603/20063820271745.jpg';" hspace=3 src="http://www.pcvz.com/Program/image/200603/20063820271212.jpg" align=center vspace=1 border=1></td>
        </tr>
    </tbody>
</table>
<br><br>显示结果如上图所示。另外一种应用与之类似，即对磁盘扇区内容的备份与恢复处理。不少防病毒软件都提供这样的功能：对硬盘引导区内容的备份，一旦硬盘引导扇区被病毒破坏后能够通过对备份数据的写入实现恢复。备份操作与前面的数据显示操作类似，只是把读取的内容不经格式处理而直接保存到指定的文件中即可：<br><br>
<table borderColor=#ffcc66 width="90%" align=center border=1>
    <tbody>
        <tr>
            <td>file.Open(fileDlg.GetPathName(), Cfile::modeCreate | Cfile::modeReadWrite);<br><br>&#8230;&#8230;<br><br>if (ReadSectors(uDiskID, m_uFrom, (UINT)dwSectorNum, bBuf) == FALSE) {<br><br>　MessageBox("所选磁盘分区不存在！", "错误", MB_OK | MB_IConERROR);<br><br>　return;<br><br>}<br><br>file.Write(bBuf, dwSectorNum * 512);<br><br>file.Close();</td>
        </tr>
    </tbody>
</table>
<br><br>数据的恢复处理正好与之相反，首先打开备份文件并根据文件长度计算要写的扇区数，然后读取其内容到缓存，最后将其写入到指定扇区完成数据的恢复：<br><br>
<table borderColor=#ffcc66 width="90%" align=center border=1>
    <tbody>
        <tr>
            <td>file.Open(fileDlg.GetPathName(), Cfile::modeReadWrite);<br><br>DWORD dwSectorNum = file.GetLength();<br><br>if (dwSectorNum % 512 != 0) return;<br><br>　dwSectorNum /= 512;<br><br>　unsigned char* bBuf = new unsigned char[dwSectorNum * 512];<br><br>　file.Read(bBuf, dwSectorNum * 512);<br><br>　if (WriteSectors(uDiskID, m_uFrom, (UINT)dwSectorNum, bBuf) == FALSE) {<br><br>MessageBox("所选磁盘分区不存在！", "错误", MB_OK | MB_IConERROR);<br><br>return;<br><br>　}<br><br>　file.Close();<br><br>　delete[] bBuf;</td>
        </tr>
    </tbody>
</table>
<br><br>面将要给出的最后一个应用是对磁盘数据的安全擦除。众所周知，在操作系统下是通过文件管理系统实现对文件访问管理的。当删除一个文件时，该文件的全部内容并没有发生任何损坏，如果没有外部数据的覆盖，完全可以通过各种数据恢复软件将先前删除的文件恢复出来。但在军工、政府等特殊的涉密行业、部门中，要求的是数据的彻底删除，即经删除过的数据是不可进行再恢复处理的。为了确保磁盘数据的可靠清空，可以对每一个扇区写入全1后再写入全0。之所以多次写入数据，是因为一次写入只能防止数据恢复软件的恢复处理。如果覆盖次数不多的化，通过一种被称做&#8220;磁盘放大镜&#8221;的特殊仪器仍能够以物理的方法将先前删除的数据恢复出来，因此这里需要对扇区多次重复写入数据，反复次数越多擦除效果越好。下面是这部分的具体实现代码：<br><br>
<table borderColor=#ffcc66 width="90%" align=center border=1>
    <tbody>
        <tr>
            <td>unsigned char bBuf[512];<br><br>UINT i = 0;<br><br>BOOL bRet = TRUE;<br><br>while (m_bAllDisk){<br><br>　memset(bBuf, 0xFF, sizeof(bBuf));<br><br>　bRet = WriteSectors(uDiskID, i, 1, bBuf);<br><br>　memset(bBuf, 0, sizeof(bBuf));<br><br>　bRet = WriteSectors(uDiskID, i, 1, bBuf);<br><br>　if (bRet == FALSE){<br><br>if (i == 0)<br><br>　MessageBox("所选磁盘分区不存在！", "错误", MB_OK | MB_IConERROR);<br><br>else<br><br>　MessageBox("磁盘数据擦除完毕！", "错误", MB_OK | MB_IConERROR);<br><br>　return;<br><br>　}<br><br>　i++;<br><br>} </td>
        </tr>
    </tbody>
</table>
<br><br><strong>小结</strong><br><br>本文仅对磁盘扇区内容的直接读写方法做了介绍并给出了扇区数据内容的显示、备份与恢复、磁盘数据的彻底擦除等几个主要的应用作了介绍。读者可以根据需要实现其他的应用如利用磁盘扇区内容进行身份认证、数据隐藏、磁盘删除数据的恢复等。本文所述程序代码在Windows 2000 Professional + SP4下由Microsoft Visual C++ 6.0编译通过。 <br>
<img src ="http://www.cppblog.com/bestcln/aggbug/83612.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/bestcln/" target="_blank">极品垃圾</a> 2009-05-21 22:19 <a href="http://www.cppblog.com/bestcln/articles/83612.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>UpdateData()</title><link>http://www.cppblog.com/bestcln/articles/83607.html</link><dc:creator>极品垃圾</dc:creator><author>极品垃圾</author><pubDate>Thu, 21 May 2009 14:14:00 GMT</pubDate><guid>http://www.cppblog.com/bestcln/articles/83607.html</guid><wfw:comment>http://www.cppblog.com/bestcln/comments/83607.html</wfw:comment><comments>http://www.cppblog.com/bestcln/articles/83607.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/bestcln/comments/commentRss/83607.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/bestcln/services/trackbacks/83607.html</trackback:ping><description><![CDATA[<p>UpdateData()</p>
<p>对于可以接收数据的控件，如编辑控件来说，UpdateData()函数至关重要。当控件内容发生变化时，对应的控件变量的值并没有跟着变化，同</p>
<p>样，当控件变量值变化时，控件内容也不会跟着变。<br>UpdateData()函数就是解决这个问题的。</p>
<p>UpdateData(true);把控件内容装入控件变量<br>UpdateData(false);用控件变量的值更新控件</p>
<p>如：有编辑控件IDC_EDIT1，对应的变量为字符串m_Edit1，<br>1、修改变量值并显示在控件中：<br>m_Edit1 = _T("结果为50");<br>UpdateData(false);<br>2、读取控件的值到变量中：<br>用ClassWizard为IDC_EDIT1添加EN_CHANGE消息处理函数，<br>void CEditView::OnChangeEdit1()<br>{<br>&nbsp;&nbsp;&nbsp; UpdateData(true);<br>} </p>
<img src ="http://www.cppblog.com/bestcln/aggbug/83607.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/bestcln/" target="_blank">极品垃圾</a> 2009-05-21 22:14 <a href="http://www.cppblog.com/bestcln/articles/83607.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>定时器</title><link>http://www.cppblog.com/bestcln/articles/83606.html</link><dc:creator>极品垃圾</dc:creator><author>极品垃圾</author><pubDate>Thu, 21 May 2009 14:08:00 GMT</pubDate><guid>http://www.cppblog.com/bestcln/articles/83606.html</guid><wfw:comment>http://www.cppblog.com/bestcln/comments/83606.html</wfw:comment><comments>http://www.cppblog.com/bestcln/articles/83606.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/bestcln/comments/commentRss/83606.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/bestcln/services/trackbacks/83606.html</trackback:ping><description><![CDATA[<strong><font color=#006699>一、定时器的基本使用方法<br><br></font></strong>在编程时，会经常使用到定时器。使用定时器的方法比较简单，通常告诉WINDOWS一个时间间隔，然后WINDOWS以此时间间隔周期性触发程序。通常有两种方法来实现：发送WM_TIMER消息和调用应用程序定义的回调函数。<br><br><font color=#0066ff>1.1 用WM_TIMER来设置定时器</font><br><br>先请看SetTimer这个API函数的原型
<pre>UINT_PTR SetTimer(
HWND hWnd,              // 窗口句柄
UINT_PTR nIDEvent,      // 定时器ID，多个定时器时，可以通过该ID判断是哪个定时器
UINT uElapse,           // 时间间隔,单位为毫秒
TIMERPROC lpTimerFunc   // 回调函数
);
</pre>
例如
<pre>SetTimer(m_hWnd,1,1000,NULL); //一个1秒触发一次的定时器</pre>
在MFC程序中SetTimer被封装在CWnd类中，调用就不用指定窗口句柄了，例如:<br>
<pre>UINT SetTimer(1,100,NULL); </pre>
函数反回值就是第一个参数值1，表示此定时器的ID号。<br><br>第二个参数表示要等待100毫秒时间再重新处理一次。第三个参数在这种方法中一般用NULL。<br><strong>注意：</strong>设置第二个参数时要注意，如果设置的等待时间比处理时间短，程序就会出问题了。<br><br><font color=#0066ff>1.2 调用回调函数</font><br><br>此方法首先写一个如下格式的回调函数<br>
<pre>void CALLBACK TimerProc(HWND hWnd,UINT nMsg,UINT nTimerid,DWORD dwTime);</pre>
然后再用SetTimer(1,100,TimerProc)函数来建一个定时器，第三个参数就是回调函数地址。<br><br><strong><font color=#006699>二、多个定时器的实现与应用</font></strong><br><br>我们在安装定时器时都为其指定了ID，使用多个定时器时，该ID就发挥作用了。<br>不使用MFC时，当接收到WM_TIMER消息，WPARAM wParam中的值便是该定时器的ID<br>使用MFC时就更简单了，我们为其增加WM_TIME的消息处理函数OnTimer即可，请看如下例子
<pre>void CTimerTestDlg::OnTimer(UINT nIDEvent)
{
switch (nIDEvent)
{
case 24:  ///处理ID为24的定时器
Draw1();
break;
case 25:  ///处理ID为25的定时器
Draw2();
break;
}
CDialog::OnTimer(nIDEvent);
}</pre>
当你用回调函数时，我们可以根据nTimerid的值来判断是哪个定时器，例如:
<pre>void CALLBACK TimerProc(HWND hWnd,UINT nMsg,UINT nTimerid,DWORD dwTime)
{
switch(nTimerid)
{
case 1:  ///处理ID为1的定时器
Do1();
break;
case 2:  ///处理ID为2的定时器
Do2();
break;
}
}</pre>
<font color=#006699><strong>三、取消定时器</strong></font><br><br>不再使用定时器后，我们应该调用KillTimer来取消定时，KillTimer的原型如下<br>
<pre>BOOL KillTimer(
HWND hWnd,          // 窗口句柄
UINT_PTR uIDEvent   // ID
);</pre>
在MFC程序中我们可以直接调用KillTimer(int nIDEvent)来取消定时器。<br><br>本文提供的例子代码在运行时就可以看到两个定时器都在工作，而且第一个在运行10次后就会被KILL掉。<br>
<img src ="http://www.cppblog.com/bestcln/aggbug/83606.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/bestcln/" target="_blank">极品垃圾</a> 2009-05-21 22:08 <a href="http://www.cppblog.com/bestcln/articles/83606.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SetTimer</title><link>http://www.cppblog.com/bestcln/articles/83604.html</link><dc:creator>极品垃圾</dc:creator><author>极品垃圾</author><pubDate>Thu, 21 May 2009 13:20:00 GMT</pubDate><guid>http://www.cppblog.com/bestcln/articles/83604.html</guid><wfw:comment>http://www.cppblog.com/bestcln/comments/83604.html</wfw:comment><comments>http://www.cppblog.com/bestcln/articles/83604.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/bestcln/comments/commentRss/83604.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/bestcln/services/trackbacks/83604.html</trackback:ping><description><![CDATA[如何使用SetTimer MFC <br>Timer事件，即定时器事件，是在游戏编程中，经常使用的一个事件。借助它可以产生定时执行动作的效果。这篇文章，就和大家一起探讨一下如何使用SetTimer（）函数。 <br>1、SetTimer定义在那里？ <br><br>SetTimer表示的是定义个定时器。根据定义指定的窗口，在指定的窗口（CWnd）中实现OnTimer事件，这样，就可以相应事件了。 <br><br>SetTimer有两个函数。一个是全局的函数::SetTimer() <br><br>UINT SetTimer( <br>HWND hWnd, // handle of window for timer messages <br>UINT nIDEvent, // timer identifier <br>UINT uElapse, // time-out value <br>TIMERPROC lpTimerFunc // address of timer procedure <br>); <br><br>其中hWnd 是指向CWnd的指针，即处理Timer事件的窗口类。说道窗口类（CWnd），我们有必要来看一下CWnd的继承情况：CWnd有以下子类：CFrameWnd,CDialog,CView,CControlBar等类。这也意味这些类中都可以定义SetTimer事件。 <br><br>同时，SetTimer（）在CWnd中也有定义，即SetTimer（）是CWnd的一个成员函数。CWnd的子类可以调用该函数，来设置触发器。 <br><br>UINT SetTimer( UINT nIDEvent, UINT nElapse, void (CALLBACK EXPORT* lpfnTimer)(HWND, UINT, UINT, DWORD) ); <br><br>参数含义： <br><br>nIDEvent:是指设置这个定时器的iD，即身份标志，这样在OnTimer（）事件中，才能根据不同的定时器，来做不同的事件响应。这个ID是一个无符号的整型。 <br><br>nElapse <br><br>是指时间延迟。单位是毫秒。这意味着，每隔nElapse毫秒系统调用一次Ontimer（）。 <br><br>void (CALLBACK EXPORT* lpfnTimer)(HWND, UINT, UINT, DWORD) <br><br>Specifies the address of the application-supplied TimerProc callback function that processes the WM_TIMER messages. If this parameter is NULL, the WM_TIMER messages are placed in the application&#8217;s message queue and handled by the CWnd object。 <br><br>意思是，指定应用程序提供的TimerProc回调函数的地址，来处里这个Timer事件。如果是NULL，处理这个Timer事件的定义这个Timer的CWnd对象。他将WM_TIMER消息传递给这个对象，通过实现这个对象的OnTimer（）事件来处理这个Timer事件。 <br><br>所以，一般情况下，我们将这个值设为NULL，有设置该定时器的对象中的OnTimer（）函数来处理这个事件。 <br><br>同样的，我们再看看KillTimer（）和OnTimer（）的定义: <br><br>KillTimer同SetTimer（）一样，他也有两个，一个是全局的::KillTimer(),另一个是CWnd的一个函数。他的声明如下： <br><br><br><br>//全局函数 <br><br>BOOL KillTimer( <br>HWND hWnd, // handle of window that installed timer <br>UINT uIDEvent // timer identifier <br>); <br><br>//CWnd函数 <br><br>BOOL KillTimer( int nIDEvent ); <br><br>这两个函数表示的意思是将iD为nIDEVENT的定时器移走。使其不再作用。其用法如同SetTimer（）一样。 <br><br>再看看OnTimer（） <br><br>CWnd::OnTimer <br>afx_msg void OnTimer( UINT nIDEvent ); <br><br>ontimer（）是响应CWnd对象产生的WM_Timer消息。nIDEvent表示要响应TIMER事件的ID。 <br><br>二、Timer事件的使用： <br><br>由以上的分析，我们应该很清楚，如何来使用Timer事件。假定我们在视图上画一个渐变的动画。我们首先在菜单栏上添加一个菜单项，给这个菜单添加命令响应： <br><br>pView-&gt;SetTimer(1,1000,NULL);//pView是视图类的指针，这里是在视图类当中设置一个定时器。 <br><br>添加完毕，再给视图类添加一个WM_Timer事件的相应。在OnTimer（）函数中编写汉书，进行相应。 <br><br>如此，就能做出动画。 <br>
<img src ="http://www.cppblog.com/bestcln/aggbug/83604.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/bestcln/" target="_blank">极品垃圾</a> 2009-05-21 21:20 <a href="http://www.cppblog.com/bestcln/articles/83604.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>MFC绘图（转载）</title><link>http://www.cppblog.com/bestcln/articles/83189.html</link><dc:creator>极品垃圾</dc:creator><author>极品垃圾</author><pubDate>Sun, 17 May 2009 08:22:00 GMT</pubDate><guid>http://www.cppblog.com/bestcln/articles/83189.html</guid><wfw:comment>http://www.cppblog.com/bestcln/comments/83189.html</wfw:comment><comments>http://www.cppblog.com/bestcln/articles/83189.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/bestcln/comments/commentRss/83189.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/bestcln/services/trackbacks/83189.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 1 几何对象的结构和类为了使用绘图函数，应该先了解绘图所用到的几种表示几何对象的结构和类。这些结构和类分别定义在头文件windef.h和afxwin.h中。1．点1）点结构POINT点数据结构POINT用来表示一点的x、y坐标：typedef struct tagPOINT { &nbsp;&nbsp;&nbsp; LONG x; &nbsp;&nbsp;&nbsp; ...&nbsp;&nbsp;<a href='http://www.cppblog.com/bestcln/articles/83189.html'>阅读全文</a><img src ="http://www.cppblog.com/bestcln/aggbug/83189.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/bestcln/" target="_blank">极品垃圾</a> 2009-05-17 16:22 <a href="http://www.cppblog.com/bestcln/articles/83189.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>什么是线性插值原理 什么是双线性插值? </title><link>http://www.cppblog.com/bestcln/articles/82865.html</link><dc:creator>极品垃圾</dc:creator><author>极品垃圾</author><pubDate>Wed, 13 May 2009 12:29:00 GMT</pubDate><guid>http://www.cppblog.com/bestcln/articles/82865.html</guid><wfw:comment>http://www.cppblog.com/bestcln/comments/82865.html</wfw:comment><comments>http://www.cppblog.com/bestcln/articles/82865.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/bestcln/comments/commentRss/82865.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/bestcln/services/trackbacks/82865.html</trackback:ping><description><![CDATA[<p>简单比方 <br>原来的数值序列：0，10，20，30，40 <br>线性插值一次为：0，5，10，15，20，25，30，35，40 <br>即认为其变化（增减）是线形的，可以在坐标图上画出一条直线 <br>在数码相机技术中，这些数值可以代表组成一张照片的不同像素点的色彩、色度等指标。</p>
<p>&nbsp;</p>
<p>为了方便理解，先考虑一维情况下的线性插值 <br>对于一个数列c，我们假设c[a]到c[a+1]之间是线性变化的 <br>那么对于浮点数x(a&lt;=x&lt;a+1)，c(x)=c[a+1]*(x-a)+c[a]*(1+a-x); <br>这个好理解吧？ </p>
<p>把这种插值方式扩展到二维情况 <br>对于一个二维数组c，我们假设对于任意一个浮点数i,c(a,i)到c(a+1,i)之间是线性变化的,c(i,b)到c(i,b+1)之间也是线性变化的(a,b都是整数) <br>那么对于浮点数的坐标(x,y)满足(a&lt;=x&lt;a+1,b&lt;=y&lt;b+1)，我们可以先分别求出c(x,b)和c(x,b+1): <br>c(x,b) = c[a+1]*(x-a)+c[a]*(1+a-x); <br>c(x,b+1) = c[a+1][b+1]*(x-a)+c[a][b+1]*(1+a-x); <br>好，现在已经知道c(x,b)和c(x,b+1)了，而根据假设c(x,b)到c(x,b+1)也是线性变化的，所以: <br>c(x,y) = c(x,b+1)*(y-b)+c(x,b)*(1+b-y) <br>这就是双线性插值，</p>
<img src ="http://www.cppblog.com/bestcln/aggbug/82865.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/bestcln/" target="_blank">极品垃圾</a> 2009-05-13 20:29 <a href="http://www.cppblog.com/bestcln/articles/82865.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>2次插值</title><link>http://www.cppblog.com/bestcln/articles/82861.html</link><dc:creator>极品垃圾</dc:creator><author>极品垃圾</author><pubDate>Wed, 13 May 2009 11:50:00 GMT</pubDate><guid>http://www.cppblog.com/bestcln/articles/82861.html</guid><wfw:comment>http://www.cppblog.com/bestcln/comments/82861.html</wfw:comment><comments>http://www.cppblog.com/bestcln/articles/82861.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/bestcln/comments/commentRss/82861.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/bestcln/services/trackbacks/82861.html</trackback:ping><description><![CDATA[<p><font face=宋体>&nbsp;</p>
<p align=left><span>图像的双线性插值放大算法中，目标图像中新创造的象素值，是由源图像位置在它附近的<span>2*2</span>区域<span>4</span>个邻近象素的值通过加权平均计算得出的。双线性内插值算法放大后的图像质量较高，不会出现像素值不连续的的情况。然而次算法具有低通滤波器的性质，使高频分量受损，所以可能会使图像轮廓在一定程度上变得模糊。</span></p>
<p align=center><span><a title="The four red dots show the data points and the green dot is the point at which we want to interpolate." href="http://en.wikipedia.org/wiki/File:Bilinear_interpolation.png"></a></span></p>
<h2><span><span><span><img height=367 alt="" src="mhtml:file://F:\c盘\目前的工作---前面板制作\网页摘要\双线性插值图像放大-缩小算法 - 枫路 - CSDNBlog.mht!http://p.blog.csdn.net/images/p_blog_csdn_net/Breathomn/EntryImages/20090306/image002.jpg" width=384></span></span></span></h2>
<h2><span><span><span><span>图1</span></span></span></span></h2>
<h2><span><span><span>X</span><span>方向的线性插值</span></span></span></h2>
<p align=left><span>对于标准的双线性差值算法，<span>X</span>方向的线性插值：</span></p>
<p align=left><span><img height=40 alt="" src="mhtml:file://F:\c盘\目前的工作---前面板制作\网页摘要\双线性插值图像放大-缩小算法 - 枫路 - CSDNBlog.mht!http://p.blog.csdn.net/images/p_blog_csdn_net/Breathomn/EntryImages/20090306/image003.gif" width=541>[</span><span>通用<span>1]</span></span></p>
<p align=left><span><img height=39 alt="" src="mhtml:file://F:\c盘\目前的工作---前面板制作\网页摘要\双线性插值图像放大-缩小算法 - 枫路 - CSDNBlog.mht!http://p.blog.csdn.net/images/p_blog_csdn_net/Breathomn/EntryImages/20090306/image004.gif" width=541>[</span><span>通用<span>2]</span></span></p>
<p align=left><span>具体到我们所实现的算法中，我们使Q11、Q12、Q21、Q22为光栅上相邻的四点，即P只能落于这四点其中一点上。&#916;col是当前像素离像素所属区域原点的水平距离，比如图2，各种不同的颜色代表一个区域，区域原点为区域左上角的像素。 </span></p>
<p align=left>&nbsp;</p>
<p align=left><span>&#948; R2 = Color Q22 &#8722;Color Q12 ∙&#916;col+Color Q12 ∙256 (1) </span></p>
<p align=left><span>&#948; R1 = Color Q21 &#8722;Color Q11 ∙&#916;col+Color Q11 ∙256 (2) </span></p>
<p align=left>&nbsp;</p>
<p align=left><span>其中：&#916;col=(DestColNumber∙((SrcWidth≪8)/DestWidth))&amp;255， Color(X)表示点X的颜色，具体算法使用的是24位真彩色格式。</span></p>
<h2><span><span><span>Y</span><span>方向的线性插值</span></span></span></h2>
<p align=left><span>做完<span>X</span>方向的插值后再做<span>Y</span>方向的插值，对于一般情况，有：</span></p>
<p align=left><span><span><img alt="" src="mhtml:file://F:\c盘\目前的工作---前面板制作\网页摘要\双线性插值图像放大-缩小算法 - 枫路 - CSDNBlog.mht!http://p.blog.csdn.net/images/p_blog_csdn_net/Breathomn/EntryImages/20090306/image011.gif">&nbsp;&nbsp;&nbsp;&nbsp; </span>[</span><span>通用<span>3]</span></span></p>
<p align=left><span><span>而我们的具体算法中，Y方向的线性插值方法如(3)所示。&#916;row是当前像素离像素所属区域原点的垂直距离，比如图2，各种不同的颜色代表一个区域，区域原点为区域左上角的像素。 </span></span></p>
<p align=left>&nbsp;</p>
<p align=left><span><span>Color P = &#948; R2 ∙256+ &#948; R2 &#8722;&#948; R1 ∙&#916;row ≫16 (3) </span></span></p>
<p align=left>&nbsp;</p>
<p align=left><span><span>其中：&#916;row=(DestRowNumber∙((SrcHeight≪8)/DestHeight))&amp;255，由于前面为了便于计算左移了16位，因此最后需要右移16位保持匹配。</span></span></p>
<h2><span><span><span><span><span>算法描述</span></span></span></span></span></h2>
<p align=left><span><span><span><span><span><span><span>类 C 伪码如下：</span></span></span></span></span></span></span></p>
<h2></h2>
<p align=left><span><span>
<div nogutter?>
<div>
<div><a onclick="dp.sh.Toolbar.Command('ViewSource',this);return false;" href="file:///F:/c盘/目前的工作---前面板制作/网页摘要/双线性插值图像放大-缩小算法%20-%20枫路%20-%20CSDNBlog.mht#">view plain</a><a onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="file:///F:/c盘/目前的工作---前面板制作/网页摘要/双线性插值图像放大-缩小算法%20-%20枫路%20-%20CSDNBlog.mht#">copy to clipboard</a><a onclick="dp.sh.Toolbar.Command('PrintSource',this);return false;" href="file:///F:/c盘/目前的工作---前面板制作/网页摘要/双线性插值图像放大-缩小算法%20-%20枫路%20-%20CSDNBlog.mht#">print</a><a onclick="dp.sh.Toolbar.Command('About',this);return false;" href="file:///F:/c盘/目前的工作---前面板制作/网页摘要/双线性插值图像放大-缩小算法%20-%20枫路%20-%20CSDNBlog.mht#">?</a></div>
</div>
<ol>
    <li><span><span>for</span><span>&nbsp;(目标图像第一行的像素++)&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>{&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>//&nbsp;源图像上Q12,&nbsp;Q22,&nbsp;Q11,&nbsp;Q21的选取见下一节&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;获取源图像Q12,&nbsp;Q22,&nbsp;Q11,&nbsp;Q21的颜色;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>//&nbsp;X&nbsp;方向的插值&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&#948;(R2)&nbsp;=&nbsp;(Color(Q22)&nbsp;-&nbsp;Color(Q12))&nbsp;*&nbsp;&#948;col+&nbsp;Color(Q12)&nbsp;*&nbsp;256;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&#948;(R1)&nbsp;=&nbsp;(Color(Q21)&nbsp;-&nbsp;Color(Q11))&nbsp;*&nbsp;&#948;col+&nbsp;Color(Q11)&nbsp;*&nbsp;256;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>//&nbsp;保存&nbsp;&#948;(R1)到一个临时数组，因为下一行的&#948;(R2)等于这一行的&#948;(R1)&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;temp[i++]&nbsp;=&nbsp;&#948;(R1);&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>//&nbsp;Y&nbsp;方向的插值&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;Color(P)&nbsp;=&nbsp;(&#948;(R2)&nbsp;*&nbsp;256&nbsp;+&nbsp;(&#948;(R2)&nbsp;-&nbsp;&#948;(R1))&nbsp;*&#948;row)&nbsp;&gt;&gt;&nbsp;16;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;将&nbsp;P&nbsp;输出到目标位图中。&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>}&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>for</span><span>&nbsp;(目标图像第二行到最末行)&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>{&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>for</span><span>&nbsp;(行上的像素++)&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>//&nbsp;源图像上Q12,&nbsp;Q22,&nbsp;Q11,&nbsp;Q21的选取见下一节&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;获取源图像Q12,&nbsp;Q22,&nbsp;Q11,&nbsp;Q21的颜色;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>//&nbsp;X&nbsp;方向的插值&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#948;(R2)&nbsp;=&nbsp;temp[i++];&nbsp;</span><span>//&nbsp;下一行的&#948;(R2)等于上一行的&#948;(R1)&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#948;(R1)&nbsp;=&nbsp;(Color(Q21)&nbsp;-&nbsp;Color(Q11))&nbsp;*&#948;col+&nbsp;Color(Q11)&nbsp;*&nbsp;256;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>//&nbsp;保存&nbsp;&#948;(R1)到一个临时数组，因为下一行的&#948;(R2)等于这一行的&#948;(R1)&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;temp[i++]&nbsp;=&nbsp;&#948;(R1);&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>//&nbsp;Y&nbsp;方向的插值&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Color(P)&nbsp;=&nbsp;(&#948;(R2)&nbsp;*&nbsp;256&nbsp;+&nbsp;(&#948;(R2)&nbsp;-&nbsp;&#948;(R1))&nbsp;*&nbsp;&#948;row)&nbsp;&gt;&gt;&nbsp;16;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;将&nbsp;P&nbsp;输出到目标位图中。&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>}&nbsp;&nbsp;&nbsp;&nbsp;</span></li>
</ol>
</div>
<p><textarea name=code rows=15 cols=50>for (目标图像第一行的像素++)
{
// 源图像上Q12, Q22, Q11, Q21的选取见下一节
获取源图像Q12, Q22, Q11, Q21的颜色;
// X 方向的插值
&#948;(R2) = (Color(Q22) - Color(Q12)) * &#948;col+ Color(Q12) * 256;
&#948;(R1) = (Color(Q21) - Color(Q11)) * &#948;col+ Color(Q11) * 256;
// 保存 &#948;(R1)到一个临时数组，因为下一行的&#948;(R2)等于这一行的&#948;(R1)
temp[i++] = &#948;(R1);
// Y 方向的插值
Color(P) = (&#948;(R2) * 256 + (&#948;(R2) - &#948;(R1)) *&#948;row) &gt;&gt; 16;
将 P 输出到目标位图中。
}
for (目标图像第二行到最末行)
{
for (行上的像素++)
{
// 源图像上Q12, Q22, Q11, Q21的选取见下一节
获取源图像Q12, Q22, Q11, Q21的颜色;
// X 方向的插值
&#948;(R2) = temp[i++]; // 下一行的&#948;(R2)等于上一行的&#948;(R1)
&#948;(R1) = (Color(Q21) - Color(Q11)) *&#948;col+ Color(Q11) * 256;
// 保存 &#948;(R1)到一个临时数组，因为下一行的&#948;(R2)等于这一行的&#948;(R1)
temp[i++] = &#948;(R1);
// Y 方向的插值
Color(P) = (&#948;(R2) * 256 + (&#948;(R2) - &#948;(R1)) * &#948;row) &gt;&gt; 16;
将 P 输出到目标位图中。
}
}  </textarea> </span></span></p>
<p>&#160;</p>
<p align=left>&nbsp;</p>
<h2><span><span><span>算法中</span><span>Q12, Q22, Q11, Q21</span><span>的选取</span></span></span></h2>
<p>&nbsp;</p>
<p align=left><span>我们以放大两倍为例，说明选取Q12, Q22, Q11, Q21的过程。源图像3*3区域放大为目标区域6*6区域。设以下为目标图像：</span></p>
<div>
<table cellSpacing=0 cellPadding=0 border=1>
    <tbody>
        <tr>
            <td width=31>
            <p align=center><span><span>A</span></span></p>
            </td>
            <td width=31>
            <p align=center><span><span>A</span></span></p>
            </td>
            <td width=31>
            <p align=center><span><span>B</span></span></p>
            </td>
            <td width=31>
            <p align=center><span><span>B</span></span></p>
            </td>
            <td width=31>
            <p align=center><span></span>&nbsp;</p>
            </td>
            <td width=31>
            <p align=center><span></span>&nbsp;</p>
            </td>
        </tr>
        <tr>
            <td width=31>
            <p align=center><span><span>A</span></span></p>
            </td>
            <td width=31>
            <p align=center><span><span>A</span></span></p>
            </td>
            <td width=31>
            <p align=center><span><span>B</span></span></p>
            </td>
            <td width=31>
            <p align=center><span><span>B</span></span></p>
            </td>
            <td width=31>
            <p align=center><span></span>&nbsp;</p>
            </td>
            <td width=31>
            <p align=center><span></span>&nbsp;</p>
            </td>
        </tr>
        <tr>
            <td width=31>
            <p align=center><span></span>&nbsp;</p>
            </td>
            <td width=31>
            <p align=center><span></span>&nbsp;</p>
            </td>
            <td width=31>
            <p align=center><span><span>C</span></span></p>
            </td>
            <td width=31>
            <p align=center><span><span>C</span></span></p>
            </td>
            <td width=31>
            <p align=center><span></span>&nbsp;</p>
            </td>
            <td width=31>
            <p align=center><span></span>&nbsp;</p>
            </td>
        </tr>
        <tr>
            <td width=31>
            <p align=center><span></span>&nbsp;</p>
            </td>
            <td width=31>
            <p align=center><span></span>&nbsp;</p>
            </td>
            <td width=31>
            <p align=center><span><span>C</span></span></p>
            </td>
            <td width=31>
            <p align=center><span><span>C</span></span></p>
            </td>
            <td width=31>
            <p align=center><span></span>&nbsp;</p>
            </td>
            <td width=31>
            <p align=center><span></span>&nbsp;</p>
            </td>
        </tr>
        <tr>
            <td width=31>
            <p align=center><span></span>&nbsp;</p>
            </td>
            <td width=31>
            <p align=center><span></span>&nbsp;</p>
            </td>
            <td width=31>
            <p align=center><span></span>&nbsp;</p>
            </td>
            <td width=31>
            <p align=center><span></span>&nbsp;</p>
            </td>
            <td width=31>
            <p align=center><span><span>D</span></span></p>
            </td>
            <td width=31>
            <p align=center><span><span>D</span></span></p>
            </td>
        </tr>
        <tr>
            <td width=31>
            <p align=center><span></span>&nbsp;</p>
            </td>
            <td width=31>
            <p align=center><span></span>&nbsp;</p>
            </td>
            <td width=31>
            <p align=center><span></span>&nbsp;</p>
            </td>
            <td width=31>
            <p align=center><span></span>&nbsp;</p>
            </td>
            <td width=31>
            <p align=center><span><span>D</span></span></p>
            </td>
            <td width=31>
            <p align=center><span><span>D</span></span></p>
            </td>
        </tr>
    </tbody>
</table>
</div>
<div>图2</div>
<p align=left><span>目标图像<span>A</span>像素区域对应的<span>Q21</span>，<span>Q22</span>，<span>Q11</span>，<span>Q12</span>，以红色区域为原点向右下方扩展的<span>2*2</span>区域。</span></p>
<div>
<table cellSpacing=0 cellPadding=0 border=1>
    <tbody>
        <tr>
            <td width=35>
            <p align=center><span><span>Q21</span></span></p>
            </td>
            <td width=35>
            <p align=center><span><span>Q22</span></span></p>
            </td>
            <td width=31>
            <p align=center><span></span>&nbsp;</p>
            </td>
        </tr>
        <tr>
            <td width=35>
            <p align=center><span><span>Q11</span></span></p>
            </td>
            <td width=35>
            <p align=center><span><span>Q12</span></span></p>
            </td>
            <td width=31>
            <p align=center><span></span>&nbsp;</p>
            </td>
        </tr>
        <tr>
            <td width=35>
            <p align=center><span><span></span></span>&nbsp;</p>
            </td>
            <td width=35>
            <p align=center><span></span>&nbsp;</p>
            </td>
            <td width=31>
            <p align=center><span></span>&nbsp;</p>
            </td>
        </tr>
    </tbody>
</table>
</div>
<div>图3</div>
<p align=left><span>目标图像<span>B</span>像素区域对应的<span>Q21</span>，<span>Q22</span>，<span>Q11</span>，<span>Q12</span>，以蓝色区域为原点向右下方扩展的<span>2*2</span>区域。</span></p>
<div>
<table cellSpacing=0 cellPadding=0 border=1>
    <tbody>
        <tr>
            <td width=31>
            <p><span></span>&nbsp;</p>
            </td>
            <td width=35>
            <p align=center><span><span>Q21</span></span></p>
            </td>
            <td width=35>
            <p align=center><span><span>Q22</span></span></p>
            </td>
        </tr>
        <tr>
            <td width=31>
            <p align=center><span></span>&nbsp;</p>
            </td>
            <td width=35>
            <p align=center><span><span>Q11</span></span></p>
            </td>
            <td width=35>
            <p align=center><span><span>Q12</span></span></p>
            </td>
        </tr>
        <tr>
            <td width=31>
            <p align=center><span></span>&nbsp;</p>
            </td>
            <td width=35>
            <p align=center><span></span>&nbsp;</p>
            </td>
            <td width=35>
            <p align=center><span></span>&nbsp;</p>
            </td>
        </tr>
    </tbody>
</table>
</div>
<div>图4</div>
<p align=left><span>目标图像<span>C</span>像素区域对应的<span>Q21</span>，<span>Q22</span>，<span>Q11</span>，<span>Q12</span>，以绿色区域为原点向右下方扩展的<span>2*2</span>区域。</span></p>
<div>
<table cellSpacing=0 cellPadding=0 border=1>
    <tbody>
        <tr>
            <td width=31>
            <p><span></span>&nbsp;</p>
            </td>
            <td width=35>
            <p align=center><span></span>&nbsp;</p>
            </td>
            <td width=35>
            <p align=center><span></span>&nbsp;</p>
            </td>
        </tr>
        <tr>
            <td width=31>
            <p align=center><span></span>&nbsp;</p>
            </td>
            <td width=35>
            <p align=center><span><span>Q21</span></span></p>
            </td>
            <td width=35>
            <p align=center><span><span>Q22</span></span></p>
            </td>
        </tr>
        <tr>
            <td width=31>
            <p align=center><span></span>&nbsp;</p>
            </td>
            <td width=35>
            <p align=center><span><span>Q11</span></span></p>
            </td>
            <td width=35>
            <p align=center><span><span>Q12</span></span></p>
            </td>
        </tr>
    </tbody>
</table>
</div>
<div>图5</div>
<p align=left><span>目标图像<span>D</span>像素区域对应的<span>Q21</span>，<span>Q22</span>，<span>Q11</span>，<span>Q12</span>，目标图像处于最后两行的边界情况，将<span>Q21</span>，<span>Q22</span>，<span>Q11</span>，<span>Q12</span>这四个点的值设为一样。</span></p>
<div>
<table cellSpacing=0 cellPadding=0 border=1>
    <tbody>
        <tr>
            <td width=31>
            <p><span></span>&nbsp;</p>
            </td>
            <td width=35>
            <p align=center><span></span>&nbsp;</p>
            </td>
            <td width=119>
            <p align=center><span></span>&nbsp;</p>
            </td>
        </tr>
        <tr>
            <td width=31>
            <p align=center><span></span>&nbsp;</p>
            </td>
            <td width=35>
            <p align=center><span></span>&nbsp;</p>
            </td>
            <td width=119>
            <p align=center><span></span>&nbsp;</p>
            </td>
        </tr>
        <tr>
            <td width=31>
            <p align=center><span></span>&nbsp;</p>
            </td>
            <td width=35>
            <p align=center><span></span>&nbsp;</p>
            </td>
            <td width=119>
            <p align=center><span><span>Q11=Q12=Q22=Q21</span></span></p>
            </td>
        </tr>
    </tbody>
</table>
</div>
<div>图6</div>
<p>
<p>&nbsp;</p>
<p align=left><span><img height=906 alt="" src="mhtml:file://F:\c盘\目前的工作---前面板制作\网页摘要\双线性插值图像放大-缩小算法 - 枫路 - CSDNBlog.mht!http://p.blog.csdn.net/images/p_blog_csdn_net/Breathomn/EntryImages/20090306/flow1.jpg" width=532></span></p>
<p align=left><span><img height=888 alt="" src="mhtml:file://F:\c盘\目前的工作---前面板制作\网页摘要\双线性插值图像放大-缩小算法 - 枫路 - CSDNBlog.mht!http://p.blog.csdn.net/images/p_blog_csdn_net/Breathomn/EntryImages/20090306/flow2.jpg" width=529></span></p>
<p>&#160;</p>
<h2><span><span><span>程序流程图</span></span></span></h2>
<p align=left><span>流程图右边虚线框中为相关过程的注解。</span></p>
</font>
<img src ="http://www.cppblog.com/bestcln/aggbug/82861.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/bestcln/" target="_blank">极品垃圾</a> 2009-05-13 19:50 <a href="http://www.cppblog.com/bestcln/articles/82861.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>常用数据类型使用转换详解</title><link>http://www.cppblog.com/bestcln/articles/82729.html</link><dc:creator>极品垃圾</dc:creator><author>极品垃圾</author><pubDate>Tue, 12 May 2009 12:25:00 GMT</pubDate><guid>http://www.cppblog.com/bestcln/articles/82729.html</guid><wfw:comment>http://www.cppblog.com/bestcln/comments/82729.html</wfw:comment><comments>http://www.cppblog.com/bestcln/articles/82729.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/bestcln/comments/commentRss/82729.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/bestcln/services/trackbacks/82729.html</trackback:ping><description><![CDATA[刚接触VC编程的朋友往往对许多数据类型的转换感到迷惑不解，本文将介绍一些常用数据类型的使用。<br><br>我们先定义一些常见类型变量借以说明
<p>int i = 100;<br>long l = 2001;<br>float f=300.2;<br>double d=12345.119;<br>char username[]="程佩君";<br>char temp[200];<br>char *buf;<br>CString str;<br>_variant_t v1;<br>_bstr_t v2;<br><br><font color=#6699ff><strong>一、其它数据类型转换为字符串</strong></font><br></p>
<ul>
    <li><font color=#6699ff>短整型(int)</font><br>itoa(i,temp,10);///将i转换为字符串放入temp中,最后一个数字表示十进制<br>itoa(i,temp,2); ///按二进制方式转换
    <li><font color=#6699ff>长整型(long)</font><br>ltoa(l,temp,10);
    <li><font color=#6699ff>浮点数(float,double)</font><br>用fcvt可以完成转换,这是MSDN中的例子:<br>int decimal, sign; <br>char *buffer; <br>double source = 3.1415926535; <br>buffer = _fcvt( source, 7, &amp;decimal, &amp;sign ); <br>运行结果:source: 3.1415926535 buffer: '31415927' decimal: 1 sign: 0<br>decimal表示小数点的位置,sign表示符号:0为正数，1为负数
    <li><font color=#6699ff>CString变量</font><br>str = "2008北京奥运";<br>buf = (LPSTR)(LPCTSTR)str;
    <li><font color=#6699ff>BSTR变量</font><br>BSTR bstrValue = ::SysAllocString(L"程序员"); <br>char * buf = _com_util::ConvertBSTRToString(bstrValue); <br>SysFreeString(bstrValue); <br>AfxMessageBox(buf); <br>delete(buf);
    <li><font color=#6699ff>CComBSTR变量</font><br>CComBSTR bstrVar("test"); <br>char *buf = _com_util::ConvertBSTRToString(bstrVar.m_str); <br>AfxMessageBox(buf); <br>delete(buf); <br>
    <li><font color=#6699ff>_bstr_t变量</font><br>_bstr_t类型是对BSTR的封装，因为已经重载了=操作符，所以很容易使用<br>_bstr_t bstrVar("test"); <br>const char *buf = bstrVar;///不要修改buf中的内容 <br>AfxMessageBox(buf); <br><br>
    <li><font color=#6699ff>通用方法(针对非COM数据类型)</font><br>用sprintf完成转换<br>
    <pre>char  buffer[200];
    char  c = '1';
    int   i = 35;
    long  j = 1000;
    float f = 1.7320534f;
    sprintf( buffer, "%c",c);
    sprintf( buffer, "%d",i);
    sprintf( buffer, "%d",j);
    sprintf( buffer, "%f",f);
    </pre>
    </li>
</ul>
<p><strong><font color=#6699ff>二、字符串转换为其它数据类型</font></strong><br>strcpy(temp,"123"); </p>
<ul>
    <li><font color=#6699ff>短整型(int)</font><br>i = atoi(temp);
    <li><font color=#6699ff>长整型(long)</font><br>l = atol(temp);
    <li><font color=#6699ff>浮点(double)</font><br>d = atof(temp);
    <li><font color=#6699ff>CString变量</font><br>CString name = temp;
    <li><font color=#6699ff>BSTR变量</font> <br>BSTR bstrValue = ::SysAllocString(L"程序员"); <br>...///完成对bstrValue的使用<br>SysFreeString(bstrValue); <br>
    <li><font color=#6699ff>CComBSTR变量</font><br>CComBSTR类型变量可以直接赋值<br>CComBSTR bstrVar1("test");<br>CComBSTR bstrVar2(temp);<br>
    <li><font color=#6699ff>_bstr_t变量</font><br>_bstr_t类型的变量可以直接赋值<br>_bstr_t bstrVar1("test"); <br>_bstr_t bstrVar2(temp); <br><br></li>
</ul>
<p><strong><font color=#6699ff>三、其它数据类型转换到CString</font></strong><br>使用CString的成员函数Format来转换,例如:<br></p>
<ul>
    <li>整数(int)<br>str.Format("%d",i);
    <li>浮点数(float)<br>str.Format("%f",i);
    <li>字符串指针(char *)等已经被CString构造函数支持的数据类型可以直接赋值<br>str = username;
    <li>对于Format所不支持的数据类型，可以通过上面所说的关于其它数据类型转化到char *的方法先转到char *，然后赋值给CString变量。<br></li>
</ul>
<p><strong><font color=#6699ff>四、BSTR、_bstr_t与CComBSTR</font></strong><br></p>
<ul>
    <li>CComBSTR 是ATL对BSTR的封装，_bstr_t是C++对BSTR的封装,BSTR是32位指针,但并不直接指向字串的缓冲区。<br>char *转换到BSTR可以这样: <br>BSTR b=_com_util::ConvertStringToBSTR("数据");///使用前需要加上comutil.h和comsupp.lib<br>SysFreeString(bstrValue); <br>反之可以使用<br>char *p=_com_util::ConvertBSTRToString(b);<br>delete p;<br>具体可以参考一，二段落里的具体说明。<br><br>CComBSTR与_bstr_t对大量的操作符进行了重载，可以直接进行=,!=,==等操作，所以使用非常方便。<br>特别是_bstr_t,建议大家使用它。<br></li>
</ul>
<p>&#160;</p>
<p><strong><font color=#6699ff>五、VARIANT 、_variant_t 与 COleVariant</font></strong><br></p>
<ul>
    <li>VARIANT的结构可以参考头文件VC98\Include\OAIDL.H中关于结构体tagVARIANT的定义。<br>对于VARIANT变量的赋值：首先给vt成员赋值，指明数据类型，再对联合结构中相同数据类型的变量赋值，举个例子：<br>VARIANT va;<br>int a=2001;<br>va.vt=VT_I4;///指明整型数据<br>va.lVal=a; ///赋值<br><br>对于不马上赋值的VARIANT，最好先用Void VariantInit(VARIANTARG FAR* pvarg);进行初始化,其本质是将vt设置为VT_EMPTY,下表我们列举vt与常用数据的对应关系:<br><br>
    <table cellSpacing=1 cellPadding=0 width=792 bgColor=#333333 border=0>
        <tbody>
            <tr bgColor=#ffffff>
                <td width=442>Byte bVal; </td>
                <td width=338>// VT_UI1.</td>
            </tr>
            <tr bgColor=#ffffff>
                <td width=442>Short iVal; </td>
                <td width=338>// VT_I2.</td>
            </tr>
            <tr bgColor=#ffffff>
                <td width=442>long lVal; </td>
                <td width=338>// VT_I4.</td>
            </tr>
            <tr bgColor=#ffffff>
                <td width=442>float fltVal; </td>
                <td width=338>// VT_R4.</td>
            </tr>
            <tr bgColor=#ffffff>
                <td width=442>double dblVal; </td>
                <td width=338>// VT_R8.</td>
            </tr>
            <tr bgColor=#ffffff>
                <td width=442>VARIANT_BOOL boolVal; </td>
                <td width=338>// VT_BOOL.</td>
            </tr>
            <tr bgColor=#ffffff>
                <td width=442>SCODE scode; </td>
                <td width=338>// VT_ERROR.</td>
            </tr>
            <tr bgColor=#ffffff>
                <td width=442>CY cyVal; </td>
                <td width=338>// VT_CY.</td>
            </tr>
            <tr bgColor=#ffffff>
                <td width=442>DATE date; </td>
                <td width=338>// VT_DATE.</td>
            </tr>
            <tr bgColor=#ffffff>
                <td width=442>BSTR bstrVal; </td>
                <td width=338>// VT_BSTR.</td>
            </tr>
            <tr bgColor=#ffffff>
                <td width=442>DECIMAL FAR* pdecVal </td>
                <td width=338>// VT_BYREF|VT_DECIMAL.</td>
            </tr>
            <tr bgColor=#ffffff>
                <td width=442>IUnknown FAR* punkVal; </td>
                <td width=338>// VT_UNKNOWN.</td>
            </tr>
            <tr bgColor=#ffffff>
                <td width=442>IDispatch FAR* pdispVal; </td>
                <td width=338>// VT_DISPATCH.</td>
            </tr>
            <tr bgColor=#ffffff>
                <td width=442>SAFEARRAY FAR* parray; </td>
                <td width=338>// VT_ARRAY|*.</td>
            </tr>
            <tr bgColor=#ffffff>
                <td width=442>Byte FAR* pbVal; </td>
                <td width=338>// VT_BYREF|VT_UI1.</td>
            </tr>
            <tr bgColor=#ffffff>
                <td width=442>short FAR* piVal; </td>
                <td width=338>// VT_BYREF|VT_I2.</td>
            </tr>
            <tr bgColor=#ffffff>
                <td width=442>long FAR* plVal; </td>
                <td width=338>// VT_BYREF|VT_I4.</td>
            </tr>
            <tr bgColor=#ffffff>
                <td width=442>float FAR* pfltVal; </td>
                <td width=338>// VT_BYREF|VT_R4.</td>
            </tr>
            <tr bgColor=#ffffff>
                <td width=442>double FAR* pdblVal; </td>
                <td width=338>// VT_BYREF|VT_R8.</td>
            </tr>
            <tr bgColor=#ffffff>
                <td width=442>VARIANT_BOOL FAR* pboolVal; </td>
                <td width=338>// VT_BYREF|VT_BOOL.</td>
            </tr>
            <tr bgColor=#ffffff>
                <td width=442>SCODE FAR* pscode; </td>
                <td width=338>// VT_BYREF|VT_ERROR.</td>
            </tr>
            <tr bgColor=#ffffff>
                <td width=442>CY FAR* pcyVal; </td>
                <td width=338>// VT_BYREF|VT_CY.</td>
            </tr>
            <tr bgColor=#ffffff>
                <td width=442>DATE FAR* pdate; </td>
                <td width=338>// VT_BYREF|VT_DATE.</td>
            </tr>
            <tr bgColor=#ffffff>
                <td width=442>BSTR FAR* pbstrVal; </td>
                <td width=338>// VT_BYREF|VT_BSTR.</td>
            </tr>
            <tr bgColor=#ffffff>
                <td width=442>IUnknown FAR* FAR* ppunkVal; </td>
                <td width=338>// VT_BYREF|VT_UNKNOWN.</td>
            </tr>
            <tr bgColor=#ffffff>
                <td width=442>IDispatch FAR* FAR* ppdispVal; </td>
                <td width=338>// VT_BYREF|VT_DISPATCH.</td>
            </tr>
            <tr bgColor=#ffffff>
                <td width=442>SAFEARRAY FAR* FAR* pparray; </td>
                <td width=338>// VT_ARRAY|*.</td>
            </tr>
            <tr bgColor=#ffffff>
                <td width=442>VARIANT FAR* pvarVal; </td>
                <td width=338>// VT_BYREF|VT_VARIANT.</td>
            </tr>
            <tr bgColor=#ffffff>
                <td width=442>void FAR* byref; </td>
                <td width=338>// Generic ByRef.</td>
            </tr>
            <tr bgColor=#ffffff>
                <td width=442>char cVal; </td>
                <td width=338>// VT_I1.</td>
            </tr>
            <tr bgColor=#ffffff>
                <td width=442>unsigned short uiVal; </td>
                <td width=338>// VT_UI2.</td>
            </tr>
            <tr bgColor=#ffffff>
                <td width=442>unsigned long ulVal; </td>
                <td width=338>// VT_UI4.</td>
            </tr>
            <tr bgColor=#ffffff>
                <td width=442>int intVal; </td>
                <td width=338>// VT_INT.</td>
            </tr>
            <tr bgColor=#ffffff>
                <td width=442>unsigned int uintVal; </td>
                <td width=338>// VT_UINT.</td>
            </tr>
            <tr bgColor=#ffffff>
                <td width=442>char FAR * pcVal; </td>
                <td width=338>// VT_BYREF|VT_I1.</td>
            </tr>
            <tr bgColor=#ffffff>
                <td width=442>unsigned short FAR * puiVal; </td>
                <td width=338>// VT_BYREF|VT_UI2.</td>
            </tr>
            <tr bgColor=#ffffff>
                <td width=442>unsigned long FAR * pulVal; </td>
                <td width=338>// VT_BYREF|VT_UI4.</td>
            </tr>
            <tr bgColor=#ffffff>
                <td width=442>int FAR * pintVal; </td>
                <td width=338>// VT_BYREF|VT_INT.</td>
            </tr>
            <tr bgColor=#ffffff>
                <td width=442>unsigned int FAR * puintVal; </td>
                <td width=338>//VT_BYREF|VT_UINT.</td>
            </tr>
        </tbody>
    </table>
    <br>
    <li>_variant_t是VARIANT的封装类，其赋值可以使用强制类型转换，其构造函数会自动处理这些数据类型。<br>使用时需加上#include &lt;comdef.h&gt;<br>例如：<br>long l=222;<br>ing i=100;<br>_variant_t lVal(l);<br>lVal = (long)i;<br><br>
    <li>COleVariant的使用与_variant_t的方法基本一样，请参考如下例子：<br>COleVariant v3 = "字符串", v4 = (long)1999;<br>CString str =(BSTR)v3.pbstrVal;<br>long i = v4.lVal;<br><br></li>
</ul>
<p><font color=#6699ff><strong>六、其它一些COM数据类型</strong></font></p>
<ul>
    <li>根据ProgID得到CLSID<br>HRESULT CLSIDFromProgID( LPCOLESTR lpszProgID,LPCLSID pclsid);<br>CLSID clsid;<br>CLSIDFromProgID( L"MAPI.Folder",&amp;clsid);<br>
    <li>根据CLSID得到ProgID<br>WINOLEAPI ProgIDFromCLSID( REFCLSID clsid,LPOLESTR * lplpszProgID); <br>例如我们已经定义了 CLSID_IApplication,下面的代码得到ProgID<br>LPOLESTR pProgID = 0;<br>ProgIDFromCLSID( CLSID_IApplication,&amp;pProgID);<br>...///可以使用pProgID <br>CoTaskMemFree(pProgID);//不要忘记释放 <br></li>
</ul>
<p><font color=#6699ff><strong>七、ANSI与Unicode<br></strong></font>Unicode称为宽字符型字串,COM里使用的都是Unicode字符串。</p>
<ul>
    <li>将ANSI转换到Unicode<br>(1)通过L这个宏来实现，例如: CLSIDFromProgID( L"MAPI.Folder",&amp;clsid);<br>(2)通过MultiByteToWideChar函数实现转换,例如:<br>char *szProgID = "MAPI.Folder";<br>WCHAR szWideProgID[128];<br>CLSID clsid;<br>long lLen = MultiByteToWideChar(CP_ACP,0,szProgID,strlen(szProgID),szWideProgID,sizeof(szWideProgID));<br>szWideProgID[lLen] = '\0'; <br>(3)通过A2W宏来实现,例如: <br>USES_CONVERSION; <br>CLSIDFromProgID( A2W(szProgID),&amp;clsid);
    <li>将Unicode转换到ANSI<br>(1)使用WideCharToMultiByte,例如:<br>// 假设已经有了一个Unicode 串 wszSomeString... <br>char szANSIString [MAX_PATH]; <br>WideCharToMultiByte ( CP_ACP, WC_COMPOSITECHECK, wszSomeString, -1, szANSIString, sizeof(szANSIString), NULL, NULL ); <br>(2)使用W2A宏来实现,例如:<br>USES_CONVERSION;<br>pTemp=W2A(wszSomeString); </li>
</ul>
<p><font color=#6699ff><strong>八、其它</strong></font></p>
<ul>
    <li>对消息的处理中我们经常需要将WPARAM或LPARAM等32位数据（DWORD)分解成两个16位数据（WORD),例如：<br>LPARAM lParam;<br>WORD loValue = LOWORD(lParam);///取低16位<br>WORD hiValue = HIWORD(lParam);///取高16位<br><br>
    <li>对于16位的数据(WORD)我们可以用同样的方法分解成高低两个8位数据(BYTE),例如:<br>WORD wValue;<br>BYTE loValue = LOBYTE(wValue);///取低8位<br>BYTE hiValue = HIBYTE(wValue);///取高8位<br><br>
    <li>两个16位数据（WORD）合成32位数据(DWORD,LRESULT,LPARAM,或WPARAM)<br>LONG MAKELONG( WORD wLow, WORD wHigh );<br>WPARAM MAKEWPARAM( WORD wLow, WORD wHigh ); <br>LPARAM MAKELPARAM( WORD wLow, WORD wHigh );<br>LRESULT MAKELRESULT( WORD wLow, WORD wHigh ); <br><br>
    <li>两个8位的数据(BYTE)合成16位的数据(WORD)<br>WORD MAKEWORD( BYTE bLow, BYTE bHigh ); <br><br>
    <li>从R(red),G(green),B(blue)三色得到COLORREF类型的颜色值<br>COLORREF RGB( BYTE byRed,BYTE byGreen,BYTE byBlue );<br>例如COLORREF bkcolor = RGB(0x22,0x98,0x34);<br><br>
    <li>从COLORREF类型的颜色值得到RGB三个颜色值<br>BYTE Red = GetRValue(bkcolor); ///得到红颜色<br>BYTE Green = GetGValue(bkcolor); ///得到绿颜色<br>BYTE Blue = GetBValue(bkcolor); ///得到兰颜色<br></li>
</ul>
<p><font color=#6699ff><strong>九、注意事项</strong></font><br>假如需要使用到ConvertBSTRToString此类函数,需要加上头文件comutil.h,并在setting中加入comsupp.lib或者直接加上#pragma comment( lib, "comsupp.lib" )</p>
<img src ="http://www.cppblog.com/bestcln/aggbug/82729.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/bestcln/" target="_blank">极品垃圾</a> 2009-05-12 20:25 <a href="http://www.cppblog.com/bestcln/articles/82729.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于BSTR数据类型</title><link>http://www.cppblog.com/bestcln/articles/82712.html</link><dc:creator>极品垃圾</dc:creator><author>极品垃圾</author><pubDate>Tue, 12 May 2009 09:44:00 GMT</pubDate><guid>http://www.cppblog.com/bestcln/articles/82712.html</guid><wfw:comment>http://www.cppblog.com/bestcln/comments/82712.html</wfw:comment><comments>http://www.cppblog.com/bestcln/articles/82712.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/bestcln/comments/commentRss/82712.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/bestcln/services/trackbacks/82712.html</trackback:ping><description><![CDATA[1.COM字符串类型<br>字符串的长度可能互不相同，因此跨COM边界传输特定的字符串时，需要确定它的长度，而且，字符串有时需要<br><br>分配内存。<br>2.Unicode和ANSI数据类型<br>3.OLECHAR,LPOLESTR,LPCOLESTR<br>COM的基本字符数据类型是OLECHAR,与平台无关的字符表示法。在创建该字符集时，OLECHAR的基本数据类型随操<br><br>作系统的不同而不同。如今最流行的COM平台是基于Win32_API的，而且基于此，OLECHAR就是wchar_t的typedef.&nbsp;<br><br>w表示它是Unicode字符。LPOLESTR是OLECHAR*的typedef，LPCOLESTR是同一种数据类型的const声明。<br>4.处理LPOLESTR<br>如果你试图将字符串值赋给LPOLESTR，则会收到编译错误，例如：<br>OLECHAR&nbsp;*olechar="A&nbsp;String!";//编译错误<br>反之，你应在这样的字符串前添加L前缀，如下所示：<br>LPOLESTR&nbsp;szMyString&nbsp;=&nbsp;L"This&nbsp;is&nbsp;a&nbsp;string!";<br>在使用printf()或ATLTRACE()时，这尤其重要（但通常被遗忘）<br>例如：<br>LPOLESTR&nbsp;szstr&nbsp;=&nbsp;L"Hello!";<br>ATLTRACE("string=%s",szstr);<br>编译后打印的是<br>string=T<br>显然是错误的，应该添加L前缀或OLESTR()宏，应该如下写：<br>ATLTRACE(L"string=%s",szstr);<br>或者<br>ATRTRACE(OLESTR("string=%s"<img onclick="window.open('/images/wink.gif','_blank');" alt="" hspace=2 src="http://www.blogcn.com/images/wink.gif" onload="javascript:if(this.width>screen.width/2)this.width=screen.width/2" vspace=2 border=0>,szstr);<br>下面两个函数通常用来复制字符串。第一个是ANSI函数wcscpy();<br>第二个是ATL函数，名为ocscpy()<br>4.是否执行Unicode编译<br>实际上在默认情况下，ATL向导既创建了ANSI配置，又创建了Unicode配置，这使你能够一种格式或两种格式编译<br><br>及发布组件服务程序，你只需坚持使用TCHAR数据类型，以便你的代码可以兼容两种字符集。<br>5.TCHAR<br>TCHAR是一般的字符类型。TCHAR的定义如下：<br>#ifdef&nbsp;UNICODE<br>typedef&nbsp;WCHAR&nbsp;TCHAT<br>#else<br>typedef&nbsp;char&nbsp;TCHAR<br>#endif<br>默认情况下，C++字符串文字为char*类型，通过在字符串前使用L前缀，可以将他们指定为宽字符。<br>在TCHAR*数据类型，应该使用_T，例如：<br>TCHAR&nbsp;*p_tchar&nbsp;=&nbsp;_T("this&nbsp;is&nbsp;string"<img onclick="window.open('/images/wink.gif','_blank');" alt="" hspace=2 src="http://www.blogcn.com/images/wink.gif" onload="javascript:if(this.width>screen.width/2)this.width=screen.width/2" vspace=2 border=0>;<br>此代码将字符串赋给ANSI/UNICODE兼容格式的字符串。_T是个宏，根据UNICODE来制定具体内容。<br>6.使用BSTR处理不同大小的字符串。<br>由于存在内存方面的问题，因此使用BSTR数据类型，BSTR就是指向OLECHAR字符串的指针，可以利用字符串的长<br><br>度区分BSTR，该长度不包括最后的null结尾符，而且在字符串指针之前的4个字节里指定。由于它是Unicode字符<br><br>串，所以每个字符占用2个字节，与LPOLESTR结尾方式一样，BSTR也必须以null结尾。BSTR避免了LPOLESTR的缺<br><br>陷，因为它的长度是显示指定的，所以null字符也可嵌入到BSTR中，所以BSTR可被用于发送二进制数据和简单字<br><br>符串。由于BSTR具有特殊结构，因此增加了一些特殊的API函数来处理BSTR.创建和销毁BSTR时调用这些函数。<br>(BSTR就是LPOLESTR指针，并且在指针的前面加上4个字节来表示大小)<br>7.处理BSTR的常用API函数。<br>应该使用SysAllocString()和SysFreeString()来管理BSTR类型<br>声明如下：<br>BSTR&nbsp;SysAllocString(const&nbsp;OLECHAR&nbsp;*szSource);<br>反之，使用SysAllocStringLen()来指定结果BSTR的长度。<br>所有的BSTR都必须使用SysFreeString()释放。否则会造成内存泄漏。<br>8.跨COM边界的字符串内存管理。<br>BSTR没有引用计数机制<br>（1）在传递字符串时，服务器负责什么操作。<br>COM服务器程序不应该维护跨COM边界传递的变量的引用，相反，应该进行复制。<br>在跨COM边界传递BSTR时，服务器程序的管理原则是客户程序负责释放BSTR。无论BSTR是[in]还是[out]参数。都<br><br>将如此。在将字符串传递给客户程序时，需要服务器程序释放该字符串的唯一时候是为[in,out]参数赋信值之前<br><br>。此时，客户程序传递被分配的字符串，而服务器程序释放该字符串，然后制订一个指针，他指向新分配的字符<br><br>串的位置，而且该字符串将由客户程序释放，对于服务器程序而言，管理原则始终是创建输入和输出BSTR的copy<br><br>，而不是给现有BSTR添加另一个引用。<br>例如：<br>STDMETHOD&nbsp;CstrigTest::GetValue(BSTR&nbsp;*pResult)<br>{<br>*pResult&nbsp;=&nbsp;m_str;<br>return&nbsp;S_OK;<br>}<br>//这是不对的，虽然没有&nbsp;语法错误，大违反了COM的管理规则，应该如下：<br>方法一：<br><br>STDMETHOD&nbsp;CstrigTest::GetValue(BSTR&nbsp;*pResult)<br>{<br>*pResult&nbsp;=&nbsp;SysAllocString(m_str);<br>return&nbsp;S_OK;<br>}<br>方法二：<br>STDMETHOD&nbsp;CstrigTest::GetValue(BSTR&nbsp;*pResult)<br>{<br>*pResult&nbsp;=&nbsp;m_str;<br>m_str&nbsp;=&nbsp;NULL;<br>return&nbsp;S_OK;<br>}<br>输入参数时原则相同。<br>下面是处理BSTR的指导方针：<br>（1）[in]参数必须由client拥有，所以，如果服务器程序应该创建copy，不应释放或更改这些参数。<br>(2)[out]参数由client释放。<br>（3）客户程序必须将NULL或释放的BSTR传递给服务器程序的[out]参数中。<br>（4）在服务器程序在被赋予新的BSTR值之前，[in,out]参数必须被释放。<br>（5）始终使用SysStringLen()获得BSTR的长度。<br>COM+提供了两个类函数对字符串进行封装:CComBSTR&nbsp;和_bstr_t<br>9.字符串转换函数<br>ATL字符串转换宏（在使用任何宏之前，一定要指定USER_CONVERSION宏，否则会遇到如下编译错误：error&nbsp;c2065:'_lpw'undeclared&nbsp;<br><br>identifier）<br>A2BSTR A2COLE&nbsp;A2CW&nbsp;.......(很多)<br>例如：（使用W2A宏）<br>LPOLESTR&nbsp;szString=L"this&nbsp;is&nbsp;a&nbsp;string!";<br>char&nbsp;*str;<br>str&nbsp;=&nbsp;W2A(szString);<br>所有这些宏都是以ATL为基础的，在ATL中使用这些宏时，项目必须包括atlconv.h。<br>COM+还定义了另外两个转换函数，而且有#import指令自动包含，这两个函数都位于comutil.h文件中，并从属于_com_util名称空间，他们可以<br><br>将ANSI字符串转换成BSTR，或者反向。函数为：<br>ConvertStringToBSTR()<br>ConvertBSTRToString()<br>10.CComBSTR(CComBSTR封装了BSTR)<br>如果在BSTR超出了其作用域时没有调用SysFreeString()，则系统调用会造成内存泄漏。<br>CComBSTR在ATL的atlbase.h头文件中定义，因为它在一个ATL文件中定义，所以CComBSTR在ATL项目中最常用，以从COM客户程序中来回传递字符<br><br>串。<br>CComBSTR只有一个数据成员，名为m_str的公共BSTR。CComBSTR的用途是封装BSTR数据类型，以帮助BSTR的内存管理。还有ToUpper(),ToLower(<br><br>)等将字符串转换为特定的大小写格式。<br>（在构造函数种分配内存，在析构函数中释放内存）。<br>在赋值，实例化，删除时内存管理非常关键。<br>Attach()转移所有权。<br>必须是m_str=NULL时才能使用Attach()<br>Detach()用于释放所有权，<br>BSTR&nbsp;Detach()<br>{<br>BSTR&nbsp;s&nbsp;=&nbsp;m_str;<br>m_str&nbsp;=&nbsp;NULL;<br>return&nbsp;s;<br>}<br>Copy()函数用于复制字符串。<br>11._bstr_t<br>_bstr_t保持内部的引用计数<br>_bstr_t是由#import指令自动添加的。与CComBSTR的最大区别是保持了一个内部引用。另一个区别是_bstr_t要求异常处理，ATL项目不会包括<br><br>异常处理，因此_bstr_t更适合于COM客户程序，_bstr_t的定义与实现位于comutil.h中。<br>一个通用的原则是：_bstr_t类应用于COM客户程序，而CComBSTR应用于ATL服务器程序。<br>12.其它数据类型<br>1.COM数据类型<br>COM&nbsp;name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;C++&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;size<br>Byte&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BYTE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8<br>Boolean&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;VARIANT_BOOL&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;16<br>Double&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;double&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;64<br>Float&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;float&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;32<br>Integer&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>Long&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;long&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;32<br>Short&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;short&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;16<br>String&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BSTR<br>Date&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DATE<br>Variant&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;VARIANT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>Dispatch&nbsp;Interface&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IDispatch*<br>Unknown&nbsp;Interface&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IUnknown*<br>2.VARIANT结构<br>3._variant_t<br>_variant_t是micsoft特有的，它是VARIANT的C++封装器类<br>4.传递数组<br>传递数组的类型为：SAFEARRAY**。<br>
<img src ="http://www.cppblog.com/bestcln/aggbug/82712.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/bestcln/" target="_blank">极品垃圾</a> 2009-05-12 17:44 <a href="http://www.cppblog.com/bestcln/articles/82712.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>_variant_t 是什么数据类型？？</title><link>http://www.cppblog.com/bestcln/articles/82711.html</link><dc:creator>极品垃圾</dc:creator><author>极品垃圾</author><pubDate>Tue, 12 May 2009 09:43:00 GMT</pubDate><guid>http://www.cppblog.com/bestcln/articles/82711.html</guid><wfw:comment>http://www.cppblog.com/bestcln/comments/82711.html</wfw:comment><comments>http://www.cppblog.com/bestcln/articles/82711.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/bestcln/comments/commentRss/82711.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/bestcln/services/trackbacks/82711.html</trackback:ping><description><![CDATA[这个问题的答案比较广泛： &nbsp; <br>&nbsp; 我所知道常用的 &nbsp; <br>&nbsp; 1。在执行的SQL语句一般都是_bstr_t &nbsp; <br>&nbsp; 2.Connection &nbsp; 中的RecordsAffected &nbsp; 为VARIANT &nbsp; <br>&nbsp; 3.使用get_Value()获得的记录的值为 &nbsp; VAARIANT &nbsp; <br>&nbsp; &nbsp; &nbsp; 等等。。。 &nbsp; <br>&nbsp; _bstr_t &nbsp; 中记录了字符串的长度， &nbsp; <br>&nbsp; _variant_t &nbsp; 记录有数据的类型和数据的值 &nbsp; <br>&nbsp; &nbsp; &nbsp; 如 &nbsp; _variant_t &nbsp; ttt; &nbsp; <br>&nbsp; &nbsp; &nbsp; ttt.vt=I4_VT; &nbsp; 表示数据类型为整数 &nbsp; <br>&nbsp; &nbsp; &nbsp; ttt.lVal &nbsp; 为数据的值
<img src ="http://www.cppblog.com/bestcln/aggbug/82711.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/bestcln/" target="_blank">极品垃圾</a> 2009-05-12 17:43 <a href="http://www.cppblog.com/bestcln/articles/82711.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>vc定义全局变量</title><link>http://www.cppblog.com/bestcln/articles/82658.html</link><dc:creator>极品垃圾</dc:creator><author>极品垃圾</author><pubDate>Tue, 12 May 2009 01:53:00 GMT</pubDate><guid>http://www.cppblog.com/bestcln/articles/82658.html</guid><wfw:comment>http://www.cppblog.com/bestcln/comments/82658.html</wfw:comment><comments>http://www.cppblog.com/bestcln/articles/82658.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/bestcln/comments/commentRss/82658.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/bestcln/services/trackbacks/82658.html</trackback:ping><description><![CDATA[<div><font style="FONT-SIZE: 12px">全局变量一般这样定义：<br>1。在一类的.cpp中定义 int myInt;<br>然后再在要用到的地方的.cpp里extern int myInt；这样就可以用了。</font>
<p><font style="FONT-SIZE: 12px">2。在stdafx.cpp中加入:<br>int myInt;<br>然后在stdafx.h中加入:<br>extern int myInt<br>这样定义以后无论在什么文件中都是可见的.</font></p>
<p><font style="FONT-SIZE: 12px">3。比较规范的是，先定义一个Glbs.h，把所有的全局变量原始定义放进去。然后定义一个Externs.h，把你先前定义在Glbs.h中的变量都加上extern。注意：如果你在Glbs.h中设置了初值，那么在Externs.h中就不要加值了。然后调用时，第一次调用的＃i nclude &lt;Glbs.h&gt;，以后调用的＃i nclude &lt;Externs.h&gt;</font></p>
<p><font style="FONT-SIZE: 12px">另：</font></p>
<p><font style="FONT-SIZE: 12px">问：如何在VC++中使用全局变量，以使文档中的所有类都能访问。<br>　　答：把该变量放到该应用程序类的头文件中的attribute处。然后，在程序的任何地方，你都可以用下面的方法来访问该变量：<br>　　CMyApp *app=（CMyApp*）AfxGet-App（）；<br>　　app-&gt;MyGlobalVariable=&#8230;<br>　　用这个方法，不但可以定义全局变量，也可以定义全局对象。<br>　　例如：<br>　　MyClass MyObject；<br>　　CMyApp*app=（CMyApp*）AfxGet-App（）；<br>　　app-&gt;MyObject.MyFunction（）；</font></p>
<p><font style="FONT-SIZE: 12px">&nbsp;</font></p>
<p><font style="FONT-SIZE: 12px">VC中使用全局变量的2种办法及防错措施</font></p>
<p><font style="FONT-SIZE: 12px">&nbsp;&nbsp;<br>&nbsp; 1. 对于全局变量存在和函数一样的问题，为了在其他CPP文件中能够访问这些变量，必须在主文件的H文件中加上extern声明，格式如下：<br>extern varibletype var; （声明）<br>在主文件的CPP文件中定义<br>varibletype var; （定义）<br>例子:<br>AppWizard建立一个Test工程<br>那么在Test.h中声明extern CString cs;<br>在Test.app定义CString cs;</font></p>
<p><font style="FONT-SIZE: 12px">&nbsp;&nbsp; 如果要定义整个工程的全局变量，在任何一个CPP文件中进行定义，然后在需要引用这个变量的文件中进行声明。如全局变量很多可以选择使用定义全局变量的。h文件，在需要的地方直接include头文件即可，不需要写那么多extern了。<br>2.应用程序类的主头文件处定义变量varibletype var，然后，在程序的任何地方，都可以用下面的方法来访问该变量：&nbsp;<br>　　CClassApp *app=(CClassApp*)AfxGetApp();&nbsp;<br>　　app-&gt;var=<br>　类似的，以上方法也可以定义全局对象<br>例子:<br>AppWizard建立一个Test工程<br>那么在Test.h中声明 CString cs;<br>使用的时候CTestApp *app=(CTestApp*)AfxGetApp();&nbsp;<br>&nbsp;&nbsp;&nbsp; app-&gt;cs="Global"<br>&nbsp;<br>防错措施：<br>若定义的函数和全局变量在多个文件包含且造成嵌套或多次调用的话，这样将导致这个头文件每被包含依次，函数或变量就被重新定义一次，在链接编译时会导致重定义错误。为此需要使用一种被称为Guard macro的技术来保证不出错。在一个头文件开头加上&nbsp;<br>#ifndef&nbsp;&nbsp; _MACRO_1_<br>#define&nbsp;&nbsp; _MACRO_1_<br>在文件末尾增加&nbsp;<br>#endif</font></p>
</div>
<img src ="http://www.cppblog.com/bestcln/aggbug/82658.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/bestcln/" target="_blank">极品垃圾</a> 2009-05-12 09:53 <a href="http://www.cppblog.com/bestcln/articles/82658.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>VC 串口调试</title><link>http://www.cppblog.com/bestcln/articles/80270.html</link><dc:creator>极品垃圾</dc:creator><author>极品垃圾</author><pubDate>Fri, 17 Apr 2009 09:29:00 GMT</pubDate><guid>http://www.cppblog.com/bestcln/articles/80270.html</guid><wfw:comment>http://www.cppblog.com/bestcln/comments/80270.html</wfw:comment><comments>http://www.cppblog.com/bestcln/articles/80270.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/bestcln/comments/commentRss/80270.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/bestcln/services/trackbacks/80270.html</trackback:ping><description><![CDATA[<p class=article_content align=left><strong><a><span style="FONT-SIZE: 12pt">1.建立项目</span></a></strong><span style="FONT-SIZE: 12pt">：</span></p>
<p class=article_content align=left><span style="FONT-SIZE: 12pt">打开VC＋＋6.0，建立一个基于对话框的MFC应用程序SCommTest;</span></p>
<p class=article_content align=left><strong><a><span style="FONT-SIZE: 12pt">2.在项目中插入MSComm控件</span></a></strong><span style="FONT-SIZE: 12pt">&nbsp;&nbsp; </span></p>
<p class=article_content align=left><span style="FONT-SIZE: 12pt">选择Project菜单下Add To Project子菜单中的 Components and Controls&#8230;选项，在弹出的对话框中双击Registered ActiveX Controls项（稍等一会，这个过程较慢），则所有注册过的ActiveX控件出现在列表框中。 选择Microsoft Communications Control, version 6.0，，单击Insert按钮将它插入到我们的Project中来，接受缺省的选项。（如果你在控件列表中看不到Microsoft Communications Control, version 6.0，那可能是你在安装VC6时没有把ActiveX一项选上，重新安装VC6，选上ActiveX就可以了），</span></p>
<p class=article_content align=left><span style="FONT-SIZE: 12pt">这时在ClassView视窗中就可以看到CMSComm类了，（注意：此类在ClassWizard中看不到，重构clw文件也一样），并且在控件工具栏Controls中出现了电话图标（如图1所示），现在要做的是用鼠标将此图标拖到对话框中，程序运行后，这个图标是看不到的。</span></p>
<p class=article_content align=left><span style="FONT-SIZE: 12pt"><img height=224 src="http://www.gjwtech.com/pic/picvcandc/scomm01.jpg" width=172 border=0></span></p>
<p class=article_content align=left><a><strong><span style="FONT-SIZE: 12pt">3.利用ClassWizard定义CMSComm类控制对象</span></strong></a><span style="FONT-SIZE: 12pt"></span></p>
<p class=article_content align=left><span style="FONT-SIZE: 12pt">打开ClassWizard－&gt;Member Viariables选项卡，选择CSCommTestDlg类，为IDC_MSCOMM1添加控制变量：m_ctrlComm，这时你可以看一看，在对话框头文件中自动加入了//{{AFX_INCLUDES() ＃i nclude "mscomm.h" //}}AFX_INCLUDES 。</span></p>
<div class=article_content align=left><a><strong><span style="FONT-SIZE: 12pt">4.在对话框中添加控件</span></strong></a></div>
<div class=article_content align=left>&nbsp;</div>
<div class=article_content align=left><span style="FONT-SIZE: 12pt">向主对话框中添加两个编辑框，一个用于接收显示数据ID为IDC_EDIT_RXDATA，另一个用于输入发送数据，ID为IDC_EDIT_TXDATA，再添加一个按钮，功能是按一次就把发送编辑框中的内容发送一次，将其ID设为IDC_BUTTON_MANUALSEND。别忘记了将接收编辑框的Properties－&gt;Styles中把Miltiline和Vertical Scroll属性选上，发送编辑框若你想输入多行文字，也可选上Miltiline。</span></div>
<p class=article_content align=left><span style="FONT-SIZE: 12pt">再打开ClassWizard－&gt;Member Viariables选项卡，选择CSCommTestDlg类， 为IDC_EDIT_RXDATA添加CString变量m_strRXData， 为IDC_EDIT_TXDATA添加CString变量m_strTXData。说明： m_strRXData和m_strTXData分别用来放入接收和发送的字符数据。</span></p>
<p class=article_content align=left><strong><a><span style="FONT-SIZE: 12pt">5.添加串口事件消息处理函数OnComm()</span></a></strong><span style="FONT-SIZE: 12pt"></span></p>
<p class=article_content align=left><span style="FONT-SIZE: 12pt">打开ClassWizard－&gt;Message Maps，选择类CSCommTestDlg，选择IDC_MSCOMM1，双击消息OnComm，将弹出的对话框中将函数名改为OnComm。</span></p>
<p class=article_content align=left><span style="FONT-SIZE: 12pt">这个函数是用来处理串口消息事件的，如每当串口接收到数据，就会产生一个串口接收数据缓冲区中有字符的消息事件，我们刚才添加的函数就会执行，我们在OnComm()函数加入相应的处理代码就能实现自已想要的功能了。请你在函数中加入如下代码：</span></p>
<blockquote class=article_content>
<p align=left><span style="FONT-SIZE: 12pt; COLOR: #999999">void CSCommTestDlg::OnComm() <br>{<br>&nbsp;&nbsp;&nbsp; // TODO: Add your control notification handler code here<br></span><span style="FONT-SIZE: 12pt">&nbsp;&nbsp;&nbsp; VARIANT variant_inp;<br>&nbsp;&nbsp;&nbsp; COleSafeArray safearray_inp;<br>&nbsp;&nbsp;&nbsp; LONG len,k;<br>&nbsp;&nbsp;&nbsp; BYTE rxdata[2048]; //设置BYTE数组 An 8-bit integerthat is not signed.<br>&nbsp;&nbsp;&nbsp; CString strtemp;<br>&nbsp;&nbsp;&nbsp; if(m_ctrlComm.GetCommEvent()==2) //事件值为2表示接收缓冲区内有字符<br>&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ////////以下你可以根据自己的通信协议加入处理代码<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; variant_inp=m_ctrlComm.GetInput(); //读缓冲区<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; safearray_inp=variant_inp; //VARIANT型变量转换为ColeSafeArray型变量<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; len="safearray"_inp.GetOneDimSize(); //得到有效数据长度<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(k=0;k&lt;len;k++)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; safearray_inp.GetElement(&amp;k,rxdata+k);//转换为BYTE型数组<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(k=0;k&lt;len;k++) //将数组转换为Cstring型变量<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BYTE bt=*(char*)(rxdata+k); //字符型<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strtemp.Format("%c",bt); //将字符送入临时变量strtemp存放<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_strRXData+=strtemp; //加入接收编辑框对应字符串 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; UpdateData(FALSE); //更新编辑框内容<br></span><span style="FONT-SIZE: 12pt; COLOR: #999999">}<br></span></p>
</blockquote>
<p class=article_content align=left><span style="FONT-SIZE: 12pt">到目前为止还不能在接收编辑框中看到数据，因为我们还没有打开串口，但运行程序不应该有任何错误，不然，你肯定哪儿没看仔细，因为我是打开VC6对照着做一步写一行的，运行试试。没错吧？那么做下一步：</span></p>
<p class=article_content align=left><strong><a><span style="FONT-SIZE: 12pt">6.打开串口和设置串口参数</span></a></strong><span style="FONT-SIZE: 12pt"></span></p>
<p class=article_content align=left><span style="FONT-SIZE: 12pt">你可以在你需要的时候打开串口，例如在程序中做一个开始按钮，在该按钮的处理函数中打开串口。现在我们在主对话框的CSCommTestDlg::OnInitDialog()打开串口，加入如下代码：</span></p>
<p class=article_content align=left><span style="FONT-SIZE: 12pt; COLOR: #999999">// TODO: Add extra initialization here</span><br><span style="FONT-SIZE: 12pt">if(m_ctrlComm.GetPortOpen())<br>m_ctrlComm.SetPortOpen(FALSE);<br><br>m_ctrlComm.SetCommPort(1); //选择com1<br>if( !m_ctrlComm.GetPortOpen())<br>m_ctrlComm.SetPortOpen(TRUE);//打开串口<br>else<br>AfxMessageBox("cannot open serial port");<br><br>m_ctrlComm.SetSettings("9600,n,8,1"); //波特率9600，无校验，8个数据位，1个停止位</span></p>
<p class=article_content align=left><span style="FONT-SIZE: 12pt">m_ctrlComm.SetInputModel(1); //1：表示以二进制方式检取数据<br>m_ctrlComm.SetRThreshold(1); <br>//参数1表示每当串口接收缓冲区中有多于或等于1个字符时将引发一个接收数据的OnComm事件<br>m_ctrlComm.SetInputLen(0); //设置当前接收区数据长度为0<br>m_ctrlComm.GetInput();//先预读缓冲区以清除残留数据</span></p>
<p class=article_content align=left><span style="FONT-SIZE: 12pt">现在你可以试试程序了，将串口线接好后（<span style="FONT-SIZE: 12pt; COLOR: #999999">不会接？去看看我写的<a style="COLOR: #006666; TEXT-DECORATION: none" href="http://www.gjwtech.com/scomm/scconnectmethod.htm">串口接线基本方法</a></span>），打开</span><a style="COLOR: #006666; TEXT-DECORATION: none" href="http://www.gjwtech.com/myownprogram/comdebugassistant.htm"><span style="FONT-SIZE: 12pt">串口调试助手</span></a><span style="FONT-SIZE: 12pt">，并将串口设在com2，选上自动发送，也可以等会手动发送。再执行你编写的程序，接收框里应该有数据显示了。</span></p>
<p class=article_content align=left><strong><a><span style="FONT-SIZE: 12pt">7.发送数据</span></a></strong><span style="FONT-SIZE: 12pt"></span></p>
<p class=article_content align=left><span style="FONT-SIZE: 12pt">先为发送按钮添加一个单击消息即BN_CLICKED处理函数，打开ClassWizard－&gt;Message Maps，选择类CSCommTestDlg，选择IDC_BUTTON_MANUALSEND，双击BN_CLICKED添加OnButtonManualsend()函数，并在函数中添加如下代码：</span></p>
<p class=article_content align=left><span style="FONT-SIZE: 12pt; COLOR: #999999">void CSCommTestDlg::OnButtonManualsend() <br>{<br>// TODO: Add your control notification handler code here<br></span><span style="FONT-SIZE: 12pt">UpdateData(TRUE); //读取编辑框内容<br>m_ctrlComm.SetOutput(COleVariant(m_strTXData));//发送数据<br><span style="FONT-SIZE: 12pt; COLOR: #999999">}</span></span></p>
<p class=article_content align=left><span style="FONT-SIZE: 12pt">运行程序，在发送编辑框中随意输入点什么，单击发送按钮，啊！看看，在另一端的</span><a style="COLOR: #006666; TEXT-DECORATION: none" href="http://www.gjwtech.com/myownprogram/comdebugassistant.htm"><span style="FONT-SIZE: 12pt">串口调试助手</span></a><span style="FONT-SIZE: 12pt">（或别的调试工具）接收框里出现了什么。</span></p>
<p class=article_content align=left><span style="FONT-SIZE: 12pt">如果你真是初次涉猎串口编程，又一次成功，那该说声谢谢我了，因为我第一次做串口程序时可费劲了，那时网上的资料也不好找。开开玩笑，谢谢你的支持，有什么好东西别忘了给我寄一份。</span></p>
<p class=article_content align=left><span style="FONT-SIZE: 12pt">说明：</span></p>
<p class=article_content align=left><span style="FONT-SIZE: 12pt">由于用到VC控件，在没有安装VC的计算机上运行时要从VC中把mscomm32.ocx、msvcrt.dll、mfc42.dll拷到Windows目录下的System子目录中（win2000为System32）并再进行注册设置。</span></p>
<img src ="http://www.cppblog.com/bestcln/aggbug/80270.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/bestcln/" target="_blank">极品垃圾</a> 2009-04-17 17:29 <a href="http://www.cppblog.com/bestcln/articles/80270.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用标准C++的类型转换符：static_cast、dynamic_cast、reinterpret_cast、和const_cast。(转)</title><link>http://www.cppblog.com/bestcln/articles/76572.html</link><dc:creator>极品垃圾</dc:creator><author>极品垃圾</author><pubDate>Sat, 14 Mar 2009 05:20:00 GMT</pubDate><guid>http://www.cppblog.com/bestcln/articles/76572.html</guid><wfw:comment>http://www.cppblog.com/bestcln/comments/76572.html</wfw:comment><comments>http://www.cppblog.com/bestcln/articles/76572.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/bestcln/comments/commentRss/76572.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/bestcln/services/trackbacks/76572.html</trackback:ping><description><![CDATA[<p><font size=2>使用标准C++的类型转换符：static_cast、dynamic_cast、reinterpret_cast、和const_cast。</font></p>
<p><font size=2>3.1 static_cast<br>用法：static_cast &lt; type-id &gt; ( expression )&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>该运算符把expression转换为type-id类型，但没有运行时类型检查来保证转换的安全性。它主要有如下几种用法：<br>①用于类层次结构中基类和子类之间指针或引用的转换。<br>　　进行上行转换（把子类的指针或引用转换成基类表示）是安全的；<br>　　进行下行转换（把基类指针或引用转换成子类表示）时，由于没有动态类型检查，所以是不安全的。<br>②用于基本数据类型之间的转换，如把int转换成char，把int转换成enum。这种转换的安全性也要开发人员来保证。<br>③把空指针转换成目标类型的空指针。<br>④把任何类型的表达式转换成void类型。</font></p>
<p><font size=2>注意：static_cast不能转换掉expression的const、volitale、或者__unaligned属性。</font></p>
<p><br><font size=2>3.2 dynamic_cast<br>用法：dynamic_cast &lt; type-id &gt; ( expression )<br>该运算符把expression转换成type-id类型的对象。Type-id必须是类的指针、类的引用或者void *；<br>如果type-id是类指针类型，那么expression也必须是一个指针，如果type-id是一个引用，那么expression也必须是一个引用。</font></p>
<p><font size=2>dynamic_cast主要用于类层次间的上行转换和下行转换，还可以用于类之间的交叉转换。<br>在类层次间进行上行转换时，dynamic_cast和static_cast的效果是一样的；<br>在进行下行转换时，dynamic_cast具有类型检查的功能，比static_cast更安全。<br>class B{<br>public:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int m_iNum;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; virtual void foo();<br>};</font></p>
<p><font size=2>class D:public B{<br>&nbsp;&nbsp;&nbsp; public:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char *m_szName[100];<br>};</font></p>
<p><font size=2>void func(B *pb){<br>&nbsp;&nbsp;&nbsp; D *pd1 = static_cast&lt;D *&gt;(pb);<br>&nbsp;&nbsp;&nbsp; D *pd2 = dynamic_cast&lt;D *&gt;(pb);<br>}</font></p>
<p><font size=2>在上面的代码段中，如果pb指向一个D类型的对象，pd1和pd2是一样的，并且对这两个指针执行D类型的任何操作都是安全的；<br>但是，如果pb指向的是一个B类型的对象，那么pd1将是一个指向该对象的指针，对它进行D类型的操作将是不安全的（如访问m_szName），<br>而pd2将是一个空指针。</font></p>
<p><font size=2>另外要注意：B要有虚函数，否则会编译出错；static_cast则没有这个限制。<br>这是由于运行时类型检查需要运行时类型信息，而这个信息存储在类的虚函数表（<br>关于虚函数表的概念，详细可见&lt;Inside c++ object model&gt;）中，只有定义了虚函数的类才有虚函数表，<br>没有定义虚函数的类是没有虚函数表的。</font></p>
<p><font size=2>另外，dynamic_cast还支持交叉转换（cross cast）。如下代码所示。<br>class A{<br>public:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int m_iNum;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; virtual void f(){}<br>};</font></p>
<p><font size=2>class B:public A{<br>};</font></p>
<p><font size=2>class D:public A{<br>};</font></p>
<p><font size=2>void foo(){<br>&nbsp;&nbsp;&nbsp; B *pb = new B;<br>&nbsp;&nbsp;&nbsp; pb-&gt;m_iNum = 100;</font></p>
<p><font size=2>&nbsp;&nbsp;&nbsp; D *pd1 = static_cast&lt;D *&gt;(pb);&nbsp;&nbsp;&nbsp; //compile error<br>&nbsp;&nbsp;&nbsp; D *pd2 = dynamic_cast&lt;D *&gt;(pb);&nbsp; //pd2 is NULL<br>&nbsp;&nbsp;&nbsp; delete pb;<br>}</font></p>
<p><font size=2>在函数foo中，使用static_cast进行转换是不被允许的，将在编译时出错；而使用 dynamic_cast的转换则是允许的，结果是空指针。</font></p>
<p><br><font size=2>3.3 reinpreter_cast<br>用法：reinpreter_cast&lt;type-id&gt; (expression)<br>type-id必须是一个指针、引用、算术类型、函数指针或者成员指针。<br>它可以把一个指针转换成一个整数，也可以把一个整数转换成一个指针（先把一个指针转换成一个整数，<br>在把该整数转换成原类型的指针，还可以得到原先的指针值）。</font></p>
<p><font size=2>该运算符的用法比较多。</font></p>
<p><font size=2>3.4 const_cast <br>用法：const_cast&lt;type_id&gt; (expression)<br>该运算符用来修改类型的const或volatile属性。除了const 或volatile修饰之外， type_id和expression的类型是一样的。<br>常量指针被转化成非常量指针，并且仍然指向原来的对象；<br>常量引用被转换成非常量引用，并且仍然指向原来的对象；常量对象被转换成非常量对象。</font></p>
<p><font size=2>Voiatile和const类试。举如下一例：<br>class B{<br>public:<br>&nbsp;&nbsp;&nbsp;&nbsp; int m_iNum;<br>}<br>void foo(){<br>&nbsp;const B b1;<br>&nbsp;b1.m_iNum = 100;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //comile error<br>&nbsp;B b2 = const_cast&lt;B&gt;(b1);<br>&nbsp;b2. m_iNum = 200;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //fine<br>}<br>上面的代码编译时会报错，因为b1是一个常量对象，不能对它进行改变；<br>使用const_cast把它转换成一个常量对象，就可以对它的数据成员任意改变。注意：b1和b2是两个不同的对象。<br></font></p>
<img src ="http://www.cppblog.com/bestcln/aggbug/76572.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/bestcln/" target="_blank">极品垃圾</a> 2009-03-14 13:20 <a href="http://www.cppblog.com/bestcln/articles/76572.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>VC++的工程文件说明：</title><link>http://www.cppblog.com/bestcln/articles/66767.html</link><dc:creator>极品垃圾</dc:creator><author>极品垃圾</author><pubDate>Wed, 12 Nov 2008 14:18:00 GMT</pubDate><guid>http://www.cppblog.com/bestcln/articles/66767.html</guid><wfw:comment>http://www.cppblog.com/bestcln/comments/66767.html</wfw:comment><comments>http://www.cppblog.com/bestcln/articles/66767.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/bestcln/comments/commentRss/66767.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/bestcln/services/trackbacks/66767.html</trackback:ping><description><![CDATA[<p>VC++的工程文件说明：</p>
<p>VC项目文件说明<br>.dsp&nbsp;<wbr>&nbsp;<wbr> (developer studio project) 是VC++的项目文件,文本格式。项目参数配置文件，这个文件太重要，重点保护对象。&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr><br>.dsw (developer studio worksapce )工作区文件，重要性一般，因为它信息不我，容易恢复。它可以指向一个或多个.dsp文件<br>.c：源代码文件，按C语言用法编译处理。<br>.cpp：源代码文件，按C++语法编译处理。<br>.rc：资源文件。<br>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr><br>以下文件在项目中是可丢弃的，有些文件删除后，VC会自动生成的。<br>.clw ClassWizard信息文件,实际上是INI文件的格式,有兴趣可以研究一下.有时候ClassWizard出问题,手工修改CLW文件可以解决.如果此文件不存在的话,每次用ClassWizard的时候绘提示你是否重建.<br>.ncb 无编译浏览文件(no compile browser)。当自动完成功能出问题时可以删除此文件。build后会自动生成。<br>.opt 工程关于开发环境的参数文件。如工具条位置等信息；(可丢弃)&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr><br>.aps (AppStudio File),资源辅助文件,二进制格式,一般不用去管他.<br>.plg 是编译信息文件,编译时的error和warning信息文件（实际上是一个html文件）,一般用处不大.在Tools-&gt;Options里面有个选项可以控制这个文件的生成. (建立日志文件)<br>.hpj (Help Project)是生成帮助文件的工程,用microsfot Help Compiler可以处理.<br>.mdp (Microsoft DevStudio Project)是旧版本的项目文件,如果要打开此文件的话,会提示你是否转换成新的DSP格式.<br>.bsc 是用于浏览项目信息的,如果用Source Brower的话就必须有这个文件.如果不用这个功能的话,可以在Project Options里面去掉Generate Browse Info File,可以加快编译速度.<br>.map 是执行文件的映像信息纪录文件,除非对系统底层非常熟悉,这个文件一般用不着.<br>.pch (Pre-Compiled File)是预编译文件,可以加快编译速度,但是文件非常大.<br>.pdb (Program Database)记录了程序有关的一些数据和调试信息,在调试的时候可能有用.<br>.exp 只有在编译DLL的时候才会生成,记录了DLL文件中的一些信息.一般也没什么用.&nbsp;<wbr></p>
<img src ="http://www.cppblog.com/bestcln/aggbug/66767.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/bestcln/" target="_blank">极品垃圾</a> 2008-11-12 22:18 <a href="http://www.cppblog.com/bestcln/articles/66767.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>