﻿<?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++博客-winlinglin-随笔分类-Windows APIs</title><link>http://www.cppblog.com/winlinglin/category/10732.html</link><description /><language>zh-cn</language><lastBuildDate>Sun, 31 May 2009 03:46:51 GMT</lastBuildDate><pubDate>Sun, 31 May 2009 03:46:51 GMT</pubDate><ttl>60</ttl><item><title>Windows API(2) MessageBox,GetDesktopWindow</title><link>http://www.cppblog.com/winlinglin/archive/2009/05/31/86235.html</link><dc:creator>wil</dc:creator><author>wil</author><pubDate>Sun, 31 May 2009 02:57:00 GMT</pubDate><guid>http://www.cppblog.com/winlinglin/archive/2009/05/31/86235.html</guid><wfw:comment>http://www.cppblog.com/winlinglin/comments/86235.html</wfw:comment><comments>http://www.cppblog.com/winlinglin/archive/2009/05/31/86235.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/winlinglin/comments/commentRss/86235.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/winlinglin/services/trackbacks/86235.html</trackback:ping><description><![CDATA[请看一个例子：
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080">&nbsp;1</span><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">windows.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;2</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">tchar.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;3</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br></span><span style="COLOR: #008080">&nbsp;4</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br></span><span style="COLOR: #008080">&nbsp;5</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;APIENTRY&nbsp;_tWinMain(&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">&nbsp;6</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HINSTANCE&nbsp;hInstance,<br></span><span style="COLOR: #008080">&nbsp;7</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HINSTANCE&nbsp;hPrevInstance,<br></span><span style="COLOR: #008080">&nbsp;8</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LPSTR&nbsp;lpCmdLine,<br></span><span style="COLOR: #008080">&nbsp;9</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;nCmdShow<br></span><span style="COLOR: #008080">10</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)<br></span><span style="COLOR: #008080">11</span><span style="COLOR: #000000"><img id=Codehighlighter1_189_465_Open_Image onclick="this.style.display='none'; Codehighlighter1_189_465_Open_Text.style.display='none'; Codehighlighter1_189_465_Closed_Image.style.display='inline'; Codehighlighter1_189_465_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_189_465_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_189_465_Closed_Text.style.display='none'; Codehighlighter1_189_465_Open_Image.style.display='inline'; Codehighlighter1_189_465_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_189_465_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_189_465_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">12</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;UNREFERENCED_PARAMETER(&nbsp;hInstance&nbsp;);<br></span><span style="COLOR: #008080">13</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;UNREFERENCED_PARAMETER(&nbsp;hPrevInstance&nbsp;);<br></span><span style="COLOR: #008080">14</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;UNREFERENCED_PARAMETER(&nbsp;lpCmdLine&nbsp;);<br></span><span style="COLOR: #008080">15</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;UNREFERENCED_PARAMETER(&nbsp;nCmdShow&nbsp;);<br></span><span style="COLOR: #008080">16</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br></span><span style="COLOR: #008080">17</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;HWND&nbsp;hwnd&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;::GetDesktopWindow();<br></span><span style="COLOR: #008080">18</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br></span><span style="COLOR: #008080">19</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;::MessageBox(&nbsp;hwnd,&nbsp;_T(&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">First&nbsp;Windows</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;),&nbsp;_T(&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Example</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;),&nbsp;MB_OK&nbsp;);<br></span><span style="COLOR: #008080">20</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br></span><span style="COLOR: #008080">21</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">22</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<p>这个例子是大山哥哥在他的BLOG中Windows API精讲一日一练的例子。<br>奇怪吧，这次的WinMain函数又不一样了。Windows编程难学，就是因为它那么多宏，它伟大之处也是因为它的宏，可以屏蔽硬件层、字符集对程序的影响。<br>一般的WinMain函数是这样写的: int WINAPI WinMain(...)，那现在的这种又是怎样出来的呢？<br>APIENTRY在程序就是一个宏：#define APIENTRY WINAPI，那么我们就可以不管那个前缀了。<br>你肯定想不到的是，_tWinMain也是一个宏。它是定义在&lt;tchar.h&gt;中的。你可以试试将#include &lt;tchar.h&gt;去掉，你的程序肯定找不到入口点。<br>同样的，_T也是一个宏。<br>这两个宏其实是为了适应UNICODE和以前单字符的应用程序。<br>由于Windows这两个API的定义是不一样的，如下：<br>UNICODE的定义：<br>&nbsp;#define _tWinMain&nbsp;&nbsp; wWinMain<br>单字符的定义：<br>&nbsp;#define _tWinMain&nbsp;&nbsp; WinMain<br>只要经过这样的宏定义后，就可以适应不同字符宽度的函数接口了。</p>
<p>好，看函数里面。<br>函数里面第一句又是一个宏，晕...怎么老是它...不过要在Windows编程，必须爱上它。<br>这个宏与Windows API无关，UNREFERENCED_PARAMETER 展开传递的参数或表达式，其目的是避免编译器关于未引用参数的警告。当然你也可以在编译器属性那里<br>修改编译的警告级别。<br>例子中的4句宏，就是为了关掉编译器对WinMain函数4个参数未引用的报错。避免了几个警告的产生，呵呵。。。</p>
<p>GetDesktopWindow这个该不是宏了吧，哈哈。。。<br>MSDN上说：The GetDesktopWindow function returns a handle to the desktop window. The desktop window covers the entire screen. <br>The desktop window is the area on top of which other windows are painted. <br>这个函数返回了桌面的Handle，桌面大家都知道吧？</p>
<p>MessageBox想不到也是一个宏，它的定义是：<br>#ifdef UNICODE<br>#define MessageBox&nbsp; MessageBoxW<br>#else<br>#define MessageBox&nbsp; MessageBoxA<br>#endif // !UNICODE<br>很明显是为了兼容字符集参数而定义的。难道Windows API函数的参数有字符串的，都是一个宏吗？<br>MessageBox可能见得很多，最怕的大概就是&#8220;警告：内存出错，程序退出&#8221;了。<br>这是MessageBox函数的声明<br>int MessageBox(&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; HWND hWnd,<br>&nbsp;&nbsp;&nbsp; LPCTSTR lpText,<br>&nbsp;&nbsp;&nbsp; LPCTSTR lpCaption,<br>&nbsp;&nbsp;&nbsp; UINT uType<br>);<br>参数一hWnd是一个HWND，它是这个MessageBox属于的窗口的HWND,如果它为NULL,则MessageBox不属于任何一个窗口。<br>参数二lpText是这个MessageBox显示的消息内容，为了迎合Microsoft的好意，我们都应该用宏来传入参数，来兼容字符串。<br>参数三lpCaption是这个MessageBox的标题内容。<br>参数四uType则是这个MessageBox的类型，它可以改变整个MessageBox的行为和样式哦。它是一组符号标识(flags),如：MB_OK。可以用"|"操作符来进行组合<br>返回值呢？当然是你在MessageBox上的操作啦。返回值一般用宏来表示，如：IDABORT，IDOK。</p>
<img src ="http://www.cppblog.com/winlinglin/aggbug/86235.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/winlinglin/" target="_blank">wil</a> 2009-05-31 10:57 <a href="http://www.cppblog.com/winlinglin/archive/2009/05/31/86235.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Windows API(1) WinMain函数</title><link>http://www.cppblog.com/winlinglin/archive/2009/05/31/86230.html</link><dc:creator>wil</dc:creator><author>wil</author><pubDate>Sun, 31 May 2009 01:15:00 GMT</pubDate><guid>http://www.cppblog.com/winlinglin/archive/2009/05/31/86230.html</guid><wfw:comment>http://www.cppblog.com/winlinglin/comments/86230.html</wfw:comment><comments>http://www.cppblog.com/winlinglin/archive/2009/05/31/86230.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/winlinglin/comments/commentRss/86230.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/winlinglin/services/trackbacks/86230.html</trackback:ping><description><![CDATA[<p>谁是第一个Windows API？无可置疑，当然是WinMain Function啦。<br>MSDN上说：The WinMain function is the conventional name for the user-provided entry point for a Microsoft Windows-based application.<br>即：WinMain函数是Microsoft的一个传统函数命名，它是提供给用户的Windows应用程序的入口点。<br>它的函数声明如下：<br>int WINAPI WinMain(&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;HINSTANCE hInstance,<br>&nbsp;&nbsp;&nbsp; HINSTANCE hPrevInstance,<br>&nbsp;&nbsp;&nbsp; LPSTR lpCmdLine,<br>&nbsp;&nbsp;&nbsp; int nCmdShow<br>);<br>写惯C++ console程序的人可能会很奇怪，main函数一般不是这样写吗（ int main() ）？怎么会在函数声明中间加了个词(WINAPI)呢？<br>其实WINAPI是一个宏，MSDN上说：Calling convention for system functions. This type is declared in WinDef.h as follows: #define WINAPI __stdcall<br>那么WINAPI就是指_stdcall了。<br>在网上查了一下，_stdcall还有其他同类，_cdecl _pascal _fastcall...怎么那么多的？<br>_stdcall _cdecl _pascal _fastcall这些关键字是什么意思，有什么区别呢？<br>在网上查了一下，总结一下答案：<br>（1）其实它们就是关于堆栈的一些说明，首先是函数参数压栈顺序，其次是压入堆栈的内容由谁来清除，调用者还是函数自己？ <br>&nbsp; 这些开关用来告诉编译器产生什么样的汇编代码。<br>（2）VC有两种函数调用方式&nbsp;&nbsp; 一种是__stdcall，另一种是__cdecl&nbsp;&nbsp; <br>&nbsp;函数的调用方式有两种一种是PASCAL调用方式(_stdcall)，另一种是C调用方式(_cdecl)&nbsp;&nbsp; <br>&nbsp;使用PASCAL调用方式，函数在返回到调用者之前将参数从栈中删除&nbsp;&nbsp; <br>&nbsp;使用C调用方式，参数的删除是调用者完成的&nbsp;&nbsp; <br>&nbsp;WinMain函数是由系统调用的，Windows系统规定由系统调用的函数都遵守PASCAL调用方式&nbsp;&nbsp; <br>&nbsp;但是VC中函数的缺省调用方式是__cdecl，也就是C调用方式&nbsp;&nbsp; <br>&nbsp;所以在WinMain前显示的声明。&nbsp;&nbsp; <br>&nbsp;在Windows编程中将遇到很多声明修饰符，如CALLBACK,WINAPI,PASCAL这些在Intel CPU的计算机上都是__stdcall<br>（3）__cdecl是C/C++和MFC程序默认使用的调用约定，也可以在函数声明时加上__cdecl关键字来手工指定。采用__cdecl约定时，<br>&nbsp;函数参数按照从右到左的顺序入栈，并且由调用函数者把参数弹出栈以清理堆栈。<br>&nbsp;因此，实现可变参数的函数只能使用该调用约定。<br>&nbsp;由于每一个使用__cdecl约定的函数都要包含清理堆栈的代码，所以产生的可执行文件大小会比较大。<br>&nbsp;__cdecl可以写成_cdecl。 <br>&nbsp;__stdcall调用约定用于调用Win32 API函数。采用__stdcal约定时，函数参数按照从右到左的顺序入栈，被调用的函数在返回前清理传送参数的栈，<br>&nbsp;函数参数个数固定。由于函数体本身知道传进来的参数个数，因此被调用的函数可以在返回前用一条ret n指令直接清理传递参数的堆栈。<br>&nbsp;__stdcall可以写成_stdcall。 <br>&nbsp;__fastcall约定用于对性能要求非常高的场合。__fastcall约定将函数的从左边开始的两个大小不大于<br>&nbsp;4个字节（DWORD）的参数分别放在ECX和EDX寄存器，其余的参数仍旧自右向左压栈传送，被调用的函数在返回前清理传送<br>&nbsp;参数的堆栈。<br>&nbsp;__fastcall可以写成_fastcall。<br>（4）thiscall仅仅应用于&#8220;C++&#8221;成员函数。this指针存放于CX/ECX寄存器中，参数从右到左压。thiscall不是关键词，因此不能被程序员指定。 <br>（5）naked call。当采用其他的调用约定时，如果必要的话，进入函数时编译器会产生代码来保存ESI，EDI，EBX，EBP寄存器，<br>&nbsp;退出函数时则产生代码恢复这些寄存器的内容。</p>
<p>&#183;特别说明<br>1. 在默认情况下，采用__cdecl方式,因此可以省略.<br>2. WINAPI一般用于修饰动态链接库中导出函数<br>3. CALLBACK仅用于修饰回调函数<br>4. 你可能已经发现，VC下和BCB下对WINAPI的定义不同，那么你至少理解了<br>&nbsp;&nbsp; 为什么不能直接从BCB下调用VC的dll的一个原因了。<br>&nbsp;&nbsp; <br>不查不知道，一查吓一跳，怎么那么多规则的？整理了一下思路，其实并不复杂。<br>VC默认的是_cdecl方式，Win32 API函数是用_stdcall方式的，他们都是将函数参数从右到左入栈的。<br>_cdecl方式的每个函数都有清理堆栈的代码，可以实现可变参数列表，但可执行文件大小比较大。_stdcall方式是调用者清理堆栈的。<br>_fastcall的特点是它将参数左边的两个参数放在寄存器上，比较快。其余参数还是在堆栈中，堆栈还是由函数自己清除。<br>其它就不太清楚了。</p>
<p>好，该看看函数的参数了，hInstance是当前应用程序实例的Handle.<br>第二个参数hPrevInstance应用程序上一个实例的Handle。MSDN说：如果你要知道应用程序是否有另一个实例，建议使用Mutex（互斥体）来实现。此时，我想到了<br>单例模式，用Mutex来实现只运行一个实例。<br>第三个参数lpCmdLine是一个字符串，是命令行参数。<br>第四个参数nCmdShow是一个int，指明Window应该怎么现实，Windows定义了一系列宏，来帮助记忆，以SW开头，如：SW_SHOW</p>
<p>最后是返回值，它是一个int。<br>MSDN说：If the function succeeds, terminating when it receives a WM_QUIT message, it should return the exit value contained in that message's wParam parameter. If the function terminates before entering the message loop, it should return zero.<br>如果它成功的话，它会一直运行，知道收到WM_QUIT消息，它应该返回消息的wParam参数的退出值。如果函数在进入消息循环前退出，它应该返回0。<br>&nbsp;</p>
<img src ="http://www.cppblog.com/winlinglin/aggbug/86230.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/winlinglin/" target="_blank">wil</a> 2009-05-31 09:15 <a href="http://www.cppblog.com/winlinglin/archive/2009/05/31/86230.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>