<?xml version="1.0" encoding="GBK"?>
<?xml-stylesheet href="/style/rss.css" type="text/css"?>
<rss version="2.0" xmlns:eb="http://blog.tom.com/">
<channel>
  <title>hundker In SoftEngine</title>
  <link>http://blog.tom.com/hithink2006</link>
  <description><![CDATA[软件工程的践行与反思 QQ讨论群:53090079 ]]></description>
  <language>zh</language>
  <generator>newblog.tom.com RSS</generator>
  <pubDate></pubDate>    <item>
		<title><![CDATA[ 合作论坛：齐鲁软件测试联盟 ]]></title>
		<link>http://blog.tom.com/hithink2006/article/1490.html</link>
		<description><![CDATA[ 本博合作论坛：<br>
<a href="http://www.qltesting.cn/" target="_blank">齐鲁软件测试联盟</a><br>
<img alt="" src="http://hh.a.5d6d.com/userdirs/6/c/qltest/attachments/month_0801/20080121_b00eac442f014f177067SLIiOilt0jMi.gif"><br>
<br>
&nbsp;&nbsp;&nbsp; <font size="5"><span style="font-weight: bold; color: rgb(255, 1, 2);">注册有礼有惊喜！</span></font><br>
<br> ]]></description>
		<eb:creationDate>2008-04-05 22:41:10</eb:creationDate>
		<eb:modificationDate></eb:modificationDate>
    </item>
    <item>
		<title><![CDATA[ Easy Eclipse ]]></title>
		<link>http://blog.tom.com/hithink2006/article/1450.html</link>
		<description><![CDATA[ <a href="http://sourceforge.net/projects/easyeclipse" target="_blank">http://sourceforge.net/projects/easyeclipse</a><br>
<br>
Easy Eclipse makes Eclipse &amp; Eclipse plugins easy to download,install &amp; use. We test Eclipse plugin &amp; create installers todeliver complete Eclipse-based IDEs &amp; Eclipse plug-ins for C/C++,Java, Perl, PHP, Python, Ruby. Visit http://easyeclipse.org<br> ]]></description>
		<eb:creationDate>2008-03-13 15:24:33</eb:creationDate>
		<eb:modificationDate></eb:modificationDate>
    </item>
    <item>
		<title><![CDATA[ 当标题栏被拉动的时候，它会发出哪个消息给CListCtrl????? ]]></title>
		<link>http://blog.tom.com/hithink2006/article/1291.html</link>
		<description><![CDATA[ Prevent &nbsp; CListCtrl &nbsp; column &nbsp; resizing &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; -------------------------------------------------------------------------------- &nbsp;<br>
&nbsp; The &nbsp; header &nbsp; control &nbsp; in &nbsp; the &nbsp; ListView &nbsp; control &nbsp; sends &nbsp;notification &nbsp; to &nbsp; the &nbsp; parent &nbsp; window &nbsp; (e.i. &nbsp; the &nbsp; ListView) &nbsp;before &nbsp; it &nbsp; begins &nbsp; resizing &nbsp; a &nbsp; column. &nbsp; We &nbsp; can &nbsp; override &nbsp;the &nbsp; OnNotify() &nbsp; function &nbsp; in &nbsp; the &nbsp; CListCtrl &nbsp; derived &nbsp; class &nbsp;to &nbsp; handle &nbsp; this &nbsp; notification. &nbsp; The &nbsp; code &nbsp; below &nbsp; prevents &nbsp;resizing &nbsp; of &nbsp; all &nbsp; columns. &nbsp; Note &nbsp; that &nbsp; the &nbsp; resize &nbsp; cursor &nbsp;still &nbsp; shows &nbsp; up. &nbsp; &nbsp;<br>
&nbsp; BOOL &nbsp; CMyListCtrl::OnNotify(WPARAM &nbsp; wParam, &nbsp; LPARAM &nbsp; lParam, &nbsp; LRESULT* &nbsp; pResult) &nbsp; &nbsp;<br>
&nbsp; { &nbsp;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; switch &nbsp; (((NMHDR*)lParam)-&gt;code) &nbsp;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; { &nbsp;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case &nbsp; HDN_BEGINTRACKW: &nbsp;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case &nbsp; HDN_BEGINTRACKA: &nbsp;<br>
&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; *pResult &nbsp; = &nbsp; TRUE;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // &nbsp; disable &nbsp; tracking &nbsp;<br>
&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; return &nbsp; TRUE; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // &nbsp; Processed &nbsp; message &nbsp;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp;<br>
&nbsp; &nbsp; &nbsp;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return &nbsp; CListCtrl::OnNotify(wParam, &nbsp; lParam, &nbsp; pResult); &nbsp;<br>
&nbsp; } &nbsp;<br>
&nbsp; If &nbsp; you &nbsp; want &nbsp; to &nbsp; prevent &nbsp; resizing &nbsp; of &nbsp; only &nbsp; one &nbsp; column,&nbsp; you &nbsp; should &nbsp; check &nbsp; for &nbsp; the &nbsp; value &nbsp; in &nbsp; iItem &nbsp; field &nbsp; of &nbsp;the &nbsp; HD_NOTIFY &nbsp; structure. &nbsp; The &nbsp; code &nbsp; below &nbsp; stops &nbsp; only &nbsp; the&nbsp; first &nbsp; column &nbsp; from &nbsp; being &nbsp; resized. &nbsp; &nbsp;<br>
&nbsp; &nbsp; &nbsp; &nbsp;<br>
&nbsp; BOOL &nbsp; CMyListCtrl::OnNotify(WPARAM &nbsp; wParam, &nbsp; LPARAM &nbsp; lParam, &nbsp; LRESULT* &nbsp; pResult) &nbsp; &nbsp;<br>
&nbsp; { &nbsp;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; HD_NOTIFY &nbsp; &nbsp; &nbsp; *pHDN &nbsp; = &nbsp; (HD_NOTIFY*)lParam; &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if((pHDN-&gt;hdr.code &nbsp; == &nbsp; HDN_BEGINTRACKW &nbsp; || &nbsp; pHDN-&gt;hdr.code &nbsp; == &nbsp; HDN_BEGINTRACKA) &nbsp;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &amp;&amp; &nbsp; pHDN-&gt;iItem &nbsp; == &nbsp; 0)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // &nbsp; Prevent &nbsp; only &nbsp; first &nbsp; (col# &nbsp; 0) &nbsp; from&nbsp; resizing &nbsp;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; { &nbsp;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; *pResult &nbsp; = &nbsp; TRUE; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //&nbsp; disable &nbsp; tracking &nbsp;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return &nbsp;TRUE; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // &nbsp; Processed &nbsp; message&nbsp;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp;<br>
&nbsp; &nbsp; &nbsp;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return &nbsp; CListCtrl::OnNotify(wParam, &nbsp; lParam, &nbsp; pResult); &nbsp;<br>
&nbsp; } &nbsp;<br>
&nbsp; ////////////////////////////// &nbsp;<br>
&nbsp; Prevent &nbsp; CListCtrl &nbsp; column &nbsp; resizing &nbsp; (2) &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; -------------------------------------------------------------------------------- &nbsp;<br>
&nbsp; This &nbsp; article &nbsp; was &nbsp; contributed &nbsp; by &nbsp; Charles &nbsp; Herman. &nbsp; &nbsp;<br>
&nbsp; Zafir's &nbsp; article &nbsp; Prevent &nbsp; column &nbsp; resizing &nbsp; describes &nbsp; a &nbsp;method &nbsp; to &nbsp; prevent &nbsp; resizing &nbsp; of &nbsp; columns. &nbsp; However &nbsp; the &nbsp;method &nbsp; does &nbsp; not &nbsp; prevent &nbsp; the &nbsp; cursor &nbsp; from &nbsp; changing &nbsp; its &nbsp;shape. &nbsp; Furthermore &nbsp; the &nbsp; columns &nbsp; can &nbsp; still &nbsp; be &nbsp; resized &nbsp; if&nbsp; the &nbsp; user &nbsp; double &nbsp; clicks &nbsp; on &nbsp; a &nbsp; column &nbsp; separator. &nbsp; &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; In &nbsp; this &nbsp; article &nbsp; I &nbsp; persent &nbsp; a &nbsp; method &nbsp; for &nbsp; overcoming &nbsp;these &nbsp; drawbacks. &nbsp; First, &nbsp; this &nbsp; method &nbsp; is &nbsp; presented &nbsp; for &nbsp;the &nbsp; case &nbsp; all &nbsp; columns &nbsp; are &nbsp; to &nbsp; be &nbsp; non-resizable, &nbsp; then &nbsp; it&nbsp; is &nbsp; assumed &nbsp; you &nbsp; want &nbsp; some, &nbsp; but &nbsp; not &nbsp; all, &nbsp; columns &nbsp; to &nbsp;be &nbsp; resizable. &nbsp; &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; BTW, &nbsp; Since &nbsp; my &nbsp; method &nbsp; does&nbsp; not &nbsp; prevent &nbsp; resizing &nbsp; (except &nbsp; when &nbsp; double &nbsp; clicking), &nbsp; but&nbsp; only &nbsp; prevents &nbsp; the &nbsp; resizing &nbsp; cursor &nbsp; from &nbsp; appearing, &nbsp; you &nbsp;still &nbsp; need &nbsp; to &nbsp; use &nbsp; the &nbsp; method &nbsp; described &nbsp; in &nbsp; "Prevent &nbsp;column &nbsp; resizing" &nbsp; to &nbsp; have &nbsp; it &nbsp; behave &nbsp; properly. &nbsp; &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; The &nbsp; method &nbsp; presented &nbsp; here &nbsp; requires &nbsp; the &nbsp; creation &nbsp; of &nbsp; a&nbsp; class, &nbsp; CMyHeader, &nbsp; based &nbsp; on &nbsp; the &nbsp; class &nbsp; CHeaderCtrl. &nbsp; The &nbsp;header &nbsp; from &nbsp; the &nbsp; list &nbsp; ctrl &nbsp; is &nbsp; connected &nbsp; to &nbsp; CMyHeader &nbsp;via &nbsp; the &nbsp; subclassing &nbsp; mechanism. &nbsp; CMyHeader &nbsp; will &nbsp; intercept &nbsp;the &nbsp; header &nbsp; messages &nbsp; and &nbsp; disable &nbsp; things &nbsp; we &nbsp; want &nbsp;disabled. &nbsp; &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; In &nbsp; the &nbsp; header &nbsp; file &nbsp; for &nbsp; CMyListCtrl &nbsp; define &nbsp; the &nbsp; member &nbsp; variable &nbsp; &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CMyHeader &nbsp; m_Header; &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; We &nbsp; do &nbsp; the &nbsp; subclassing &nbsp; in &nbsp; the &nbsp; OnCreate() &nbsp; function. &nbsp; &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; int &nbsp; CMyListCtrl::OnCreate(LPCREATESTRUCT &nbsp; lpCreateStruct) &nbsp; &nbsp;<br>
&nbsp; { &nbsp;<br>
&nbsp; if &nbsp; (CListCtrl::OnCreate(lpCreateStruct) &nbsp; == &nbsp; -1) &nbsp;<br>
&nbsp; return &nbsp; -1; &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; // &nbsp; Since &nbsp; I &nbsp; want &nbsp; to &nbsp; capture &nbsp; all &nbsp; messages &nbsp; passed &nbsp; to &nbsp; the &nbsp; header, &nbsp;<br>
&nbsp; // &nbsp; I &nbsp; am &nbsp; subclassing &nbsp; the &nbsp; header. &nbsp; &nbsp; Note: &nbsp; 0 &nbsp; is &nbsp; the &nbsp; ID &nbsp; for &nbsp; the &nbsp; header &nbsp;<br>
&nbsp; m_Header.SubclassDlgItem( &nbsp; 0, &nbsp; this &nbsp; ); &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; return &nbsp; 0; &nbsp;<br>
&nbsp; } &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; Next, &nbsp; using &nbsp; AppWizard &nbsp; create &nbsp; the &nbsp; class &nbsp; CMyHeader. &nbsp; Again&nbsp; using &nbsp; AppWizard, &nbsp; create &nbsp; handlers &nbsp; for &nbsp; the &nbsp; WM_SETCURSOR &nbsp;and &nbsp; WM_LBUTTONDBLCLK &nbsp; messages &nbsp; inside &nbsp; CMyHeader.cpp. &nbsp; &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; // &nbsp; MyHeader.h &nbsp; : &nbsp; header &nbsp; file &nbsp;<br>
&nbsp; // &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; ///////////////////////////////////////////////////////////////////////////// &nbsp;<br>
&nbsp; // &nbsp; CMyHeader &nbsp; window &nbsp;<br>
&nbsp; #ifndef &nbsp; __MYHEADER_H__ &nbsp;<br>
&nbsp; #define &nbsp; __MYHEADER_H__ &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; class &nbsp; CMyHeader &nbsp; : &nbsp; public &nbsp; CHeaderCtrl &nbsp;<br>
&nbsp; { &nbsp;<br>
&nbsp; // &nbsp; Construction &nbsp;<br>
&nbsp; public: &nbsp;<br>
&nbsp; CMyHeader(); &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; // &nbsp; Attributes &nbsp;<br>
&nbsp; public: &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; // &nbsp; Operations &nbsp;<br>
&nbsp; public: &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; // &nbsp; Overrides &nbsp;<br>
&nbsp; // &nbsp; ClassWizard &nbsp; generated &nbsp; virtual &nbsp; function &nbsp; overrides &nbsp;<br>
&nbsp; //{{AFX_VIRTUAL(CMyHeader) &nbsp;<br>
&nbsp; //}}AFX_VIRTUAL &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; // &nbsp; Implementation &nbsp;<br>
&nbsp; public: &nbsp;<br>
&nbsp; virtual &nbsp; ~CMyHeader(); &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; // &nbsp; Generated &nbsp; message &nbsp; map &nbsp; functions &nbsp;<br>
&nbsp; protected: &nbsp;<br>
&nbsp; //{{AFX_MSG(CMyHeader) &nbsp;<br>
&nbsp; afx_msg &nbsp; BOOL &nbsp; OnSetCursor(CWnd* &nbsp; pWnd, &nbsp; UINT &nbsp; nHitTest, &nbsp; UINT &nbsp; message); &nbsp;<br>
&nbsp; afx_msg &nbsp; void &nbsp; OnLButtonDblClk(UINT &nbsp; nFlags, &nbsp; CPoint &nbsp; point); &nbsp;<br>
&nbsp; //}}AFX_MSG &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; DECLARE_MESSAGE_MAP() &nbsp;<br>
&nbsp; }; &nbsp;<br>
&nbsp; #endif &nbsp;<br>
&nbsp; ///////////////////////////////////////////////////////////////////////////// &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; // &nbsp; MyHeader.cpp &nbsp; : &nbsp; implementation &nbsp; file &nbsp;<br>
&nbsp; // &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; #include &nbsp; "stdafx.h" &nbsp;<br>
&nbsp; #include &nbsp; "MyHeader.h" &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; #ifdef &nbsp; _DEBUG &nbsp;<br>
&nbsp; #define &nbsp; new &nbsp; DEBUG_NEW &nbsp;<br>
&nbsp; #undef &nbsp; THIS_FILE &nbsp;<br>
&nbsp; static &nbsp; char &nbsp; THIS_FILE[] &nbsp; = &nbsp; __FILE__; &nbsp;<br>
&nbsp; #endif &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; ///////////////////////////////////////////////////////////////////////////// &nbsp;<br>
&nbsp; // &nbsp; CMyHeader &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; CMyHeader::CMyHeader() &nbsp;<br>
&nbsp; { &nbsp;<br>
&nbsp; } &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; CMyHeader::~CMyHeader() &nbsp;<br>
&nbsp; { &nbsp;<br>
&nbsp; } &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; BEGIN_MESSAGE_MAP(CMyHeader, &nbsp; CHeaderCtrl) &nbsp;<br>
&nbsp; //{{AFX_MSG_MAP(CMyHeader) &nbsp;<br>
&nbsp; ON_WM_SETCURSOR() &nbsp;<br>
&nbsp; ON_WM_LBUTTONDBLCLK() &nbsp;<br>
&nbsp; //}}AFX_MSG_MAP &nbsp;<br>
&nbsp; END_MESSAGE_MAP() &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; ///////////////////////////////////////////////////////////////////////////// &nbsp;<br>
&nbsp; // &nbsp; CMyHeader &nbsp; message &nbsp; handlers &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; //////////////////////////////////////////////////////////////////// &nbsp;<br>
&nbsp; // &nbsp; Disabling &nbsp; this &nbsp; message &nbsp; handler &nbsp; prevents &nbsp; the &nbsp; cursor &nbsp; from &nbsp; &nbsp;<br>
&nbsp; // &nbsp; changing &nbsp; when &nbsp; the &nbsp; cursor &nbsp; is &nbsp; over &nbsp; the &nbsp; column &nbsp; separator &nbsp; line &nbsp;<br>
&nbsp; // &nbsp; in &nbsp; the &nbsp; header &nbsp;<br>
&nbsp; // &nbsp;<br>
&nbsp; BOOL &nbsp; CMyHeader::OnSetCursor(CWnd* &nbsp; pWnd, &nbsp; UINT &nbsp; nHitTest, &nbsp; UINT &nbsp; message) &nbsp; &nbsp;<br>
&nbsp; { &nbsp;<br>
&nbsp; return &nbsp; TRUE; &nbsp;<br>
&nbsp; // return &nbsp; CHeaderCtrl::OnSetCursor(pWnd, &nbsp; nHitTest, &nbsp; message); &nbsp;<br>
&nbsp; } &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; ///////////////////////////////////////////////////////////////// &nbsp;<br>
&nbsp; // &nbsp; Disabling &nbsp; this &nbsp; message &nbsp; handler &nbsp; prevents &nbsp; the &nbsp; column &nbsp; from &nbsp; resizing &nbsp; &nbsp;<br>
&nbsp; // &nbsp; when &nbsp; a &nbsp; double &nbsp; click &nbsp; is &nbsp; done &nbsp; on &nbsp; the &nbsp; column &nbsp; separator &nbsp; line. &nbsp;<br>
&nbsp; // &nbsp;<br>
&nbsp; void &nbsp; CMyHeader::OnLButtonDblClk(UINT &nbsp; nFlags, &nbsp; CPoint &nbsp; point) &nbsp; &nbsp;<br>
&nbsp; { &nbsp;<br>
&nbsp; // CHeaderCtrl::OnLButtonDblClk(nFlags, &nbsp; point); &nbsp;<br>
&nbsp; } &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; Next &nbsp; we &nbsp; assume &nbsp; there &nbsp; are &nbsp; some &nbsp; columns &nbsp; which &nbsp; we &nbsp; want &nbsp; to &nbsp; allow &nbsp; to &nbsp; be &nbsp; re-sized. &nbsp; &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; Inside &nbsp; the &nbsp; CMyHeader &nbsp; class &nbsp; definition &nbsp; (in &nbsp; the &nbsp; file &nbsp;MyHeader.h) &nbsp; enter &nbsp; the &nbsp; following &nbsp; declarations: &nbsp; &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; // &nbsp; Attributes &nbsp;<br>
&nbsp; protected: &nbsp;<br>
&nbsp; BOOL &nbsp; IsDragAllowed( &nbsp; CPoint &nbsp; point &nbsp; ); &nbsp;<br>
&nbsp; BOOL &nbsp; m_bAllowDrag; &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; Using &nbsp; AppWizard, &nbsp; create &nbsp; a &nbsp; handler &nbsp; for &nbsp; the &nbsp; WM_NCHITTEST &nbsp; messages &nbsp; inside &nbsp; CMyHeader.cpp. &nbsp; &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; // &nbsp; MyHeader.cpp &nbsp; : &nbsp; implementation &nbsp; file &nbsp;<br>
&nbsp; // &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; #include &nbsp; "stdafx.h" &nbsp;<br>
&nbsp; #include &nbsp; "MyHeader.h" &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; #ifdef &nbsp; _DEBUG &nbsp;<br>
&nbsp; #define &nbsp; new &nbsp; DEBUG_NEW &nbsp;<br>
&nbsp; #undef &nbsp; THIS_FILE &nbsp;<br>
&nbsp; static &nbsp; char &nbsp; THIS_FILE[] &nbsp; = &nbsp; __FILE__; &nbsp;<br>
&nbsp; #endif &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; ///////////////////////////////////////////////////////////////////////////// &nbsp;<br>
&nbsp; // &nbsp; CMyHeader &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; CMyHeader::CMyHeader() &nbsp;<br>
&nbsp; { &nbsp;<br>
&nbsp; } &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; CMyHeader::~CMyHeader() &nbsp;<br>
&nbsp; { &nbsp;<br>
&nbsp; } &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; BEGIN_MESSAGE_MAP(CMyHeader, &nbsp; CHeaderCtrl) &nbsp;<br>
&nbsp; //{{AFX_MSG_MAP(CMyHeader) &nbsp;<br>
&nbsp; ON_WM_SETCURSOR() &nbsp;<br>
&nbsp; ON_WM_LBUTTONDBLCLK() &nbsp;<br>
&nbsp; ON_WM_NCHITTEST() &nbsp;<br>
&nbsp; //}}AFX_MSG_MAP &nbsp;<br>
&nbsp; END_MESSAGE_MAP() &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; //////////////////////////////////////////////////////////////////// &nbsp;<br>
&nbsp; // &nbsp; Disabling &nbsp; this &nbsp; message &nbsp; callback &nbsp; prevents &nbsp; the &nbsp; cursor &nbsp; from &nbsp; &nbsp;<br>
&nbsp; // &nbsp; changing &nbsp; when &nbsp; the &nbsp; cursor &nbsp; is &nbsp; over &nbsp; the &nbsp; column &nbsp; separator &nbsp; line &nbsp;<br>
&nbsp; // &nbsp; in &nbsp; the &nbsp; header. &nbsp; We &nbsp; enable &nbsp; this &nbsp; callback &nbsp; only &nbsp; if &nbsp; the &nbsp; cursor &nbsp; lies &nbsp;<br>
&nbsp; // &nbsp; on &nbsp; a &nbsp; separator &nbsp; for &nbsp; which &nbsp; resizing &nbsp; has &nbsp; been &nbsp; allowed. &nbsp;<br>
&nbsp; // &nbsp;<br>
&nbsp; BOOL &nbsp; CMyHeader::OnSetCursor(CWnd* &nbsp; pWnd, &nbsp; UINT &nbsp; nHitTest, &nbsp; UINT &nbsp; message) &nbsp; &nbsp;<br>
&nbsp; { &nbsp;<br>
&nbsp; if &nbsp; (m_bAllowDrag) &nbsp;<br>
&nbsp; return &nbsp; CHeaderCtrl::OnSetCursor(pWnd, &nbsp; nHitTest, &nbsp; message); &nbsp;<br>
&nbsp; else &nbsp;<br>
&nbsp; return &nbsp; TRUE; &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; } &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; ///////////////////////////////////////////////////////////////// &nbsp;<br>
&nbsp; // &nbsp; Disabling &nbsp; this &nbsp; message &nbsp; callback &nbsp; prevents &nbsp; the &nbsp; feature &nbsp; that &nbsp; headers &nbsp;<br>
&nbsp; // &nbsp; have &nbsp; of &nbsp; resizing &nbsp; a &nbsp; column &nbsp; when &nbsp; a &nbsp; double &nbsp; click &nbsp; is &nbsp; done &nbsp; on &nbsp; the &nbsp; column &nbsp;<br>
&nbsp; // &nbsp; separator &nbsp; line. &nbsp; &nbsp; We &nbsp; enable &nbsp; this &nbsp; callback &nbsp; only &nbsp; if &nbsp; the &nbsp; cursor &nbsp; lies &nbsp;<br>
&nbsp; // &nbsp; on &nbsp; a &nbsp; separator &nbsp; for &nbsp; which &nbsp; resizing &nbsp; has &nbsp; been &nbsp; allowed. &nbsp;<br>
&nbsp; // &nbsp;<br>
&nbsp; void &nbsp; CMyHeader::OnLButtonDblClk(UINT &nbsp; nFlags, &nbsp; CPoint &nbsp; point) &nbsp; &nbsp;<br>
&nbsp; { &nbsp;<br>
&nbsp; if &nbsp; (IsDragAllowed( &nbsp; point &nbsp; )) &nbsp;<br>
&nbsp; CHeaderCtrl::OnLButtonDblClk(nFlags, &nbsp; point); &nbsp;<br>
&nbsp; } &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; /////////////////////////////////////////////////////////////// &nbsp;<br>
&nbsp; // Everytime &nbsp; there &nbsp; is &nbsp; a &nbsp; cursor &nbsp; movement &nbsp; whithin &nbsp; the &nbsp; header, &nbsp; this &nbsp;<br>
&nbsp; // function &nbsp; is &nbsp; invoked. &nbsp; &nbsp; It &nbsp; has &nbsp; the &nbsp; feature &nbsp; that &nbsp; it &nbsp; is &nbsp; invoked &nbsp; &nbsp;<br>
&nbsp; // before &nbsp; OnSetCursor(), &nbsp; &nbsp; which &nbsp; means &nbsp; we &nbsp; can &nbsp; decide &nbsp; in &nbsp; advance &nbsp;<br>
&nbsp; // whether &nbsp; we &nbsp; want &nbsp; the &nbsp; tracking &nbsp; cursor &nbsp; to &nbsp; appear. &nbsp; &nbsp; (An &nbsp; aside: &nbsp;<br>
&nbsp; // OnMouseMove() &nbsp; will &nbsp; also &nbsp; track &nbsp; mouse &nbsp; movement, &nbsp; but &nbsp; it &nbsp; is &nbsp;<br>
&nbsp; // invoked &nbsp; after &nbsp; OnSetCursor()) &nbsp;<br>
&nbsp; // &nbsp;<br>
&nbsp; UINT &nbsp; CMyHeader::OnNcHitTest(CPoint &nbsp; point) &nbsp; &nbsp;<br>
&nbsp; { &nbsp;<br>
&nbsp; // &nbsp; This &nbsp; 'point' &nbsp; is &nbsp; in &nbsp; screen &nbsp; coordinates. &nbsp; &nbsp; We &nbsp; need &nbsp; to &nbsp;<br>
&nbsp; // &nbsp; transform &nbsp; it &nbsp; to &nbsp; client &nbsp; coords &nbsp; before &nbsp; we &nbsp; test &nbsp; which &nbsp;<br>
&nbsp; // &nbsp; column &nbsp; it &nbsp; is &nbsp; in. &nbsp;<br>
&nbsp; POINT &nbsp; clientPoint &nbsp; = &nbsp; point; &nbsp;<br>
&nbsp; ScreenToClient( &nbsp; &amp;clientPoint &nbsp; ); &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; m_bAllowDrag &nbsp; = &nbsp; IsDragAllowed( &nbsp; clientPoint &nbsp; ); &nbsp;<br>
&nbsp; return &nbsp; CHeaderCtrl::OnNcHitTest(point); &nbsp;<br>
&nbsp; } &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; The &nbsp; following &nbsp; function &nbsp; is &nbsp; where &nbsp; we &nbsp; select &nbsp; the &nbsp; columns&nbsp; for &nbsp; which &nbsp; we &nbsp; want &nbsp; to &nbsp; disable &nbsp; dragging. &nbsp; &nbsp; It &nbsp; is &nbsp;assumed &nbsp; we &nbsp; have &nbsp; 5 &nbsp; columns, &nbsp; and &nbsp; we &nbsp; want &nbsp; to &nbsp; disable &nbsp;dragging &nbsp; for &nbsp; columns &nbsp; 0, &nbsp; 2, &nbsp; and &nbsp; 3. &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; ///////////////////////////////////////////////////////////// &nbsp;<br>
&nbsp; // This &nbsp; is &nbsp; the &nbsp; function &nbsp; which &nbsp; determines &nbsp; which &nbsp; column &nbsp; &nbsp;<br>
&nbsp; // the &nbsp; cursor &nbsp; is &nbsp; in, &nbsp; and &nbsp; we &nbsp; decide &nbsp; whether &nbsp; we &nbsp; want &nbsp; to &nbsp;<br>
&nbsp; // allow &nbsp; resizing &nbsp; of &nbsp; that &nbsp; column. &nbsp;<br>
&nbsp; // &nbsp;<br>
&nbsp; BOOL &nbsp; CMyHeader::IsDragAllowed( &nbsp; CPoint &nbsp; point &nbsp; ) &nbsp;<br>
&nbsp; { &nbsp;<br>
&nbsp; // &nbsp; We &nbsp; will &nbsp; extract &nbsp; information &nbsp; about &nbsp; the &nbsp; header &nbsp; &nbsp;<br>
&nbsp; // &nbsp; using &nbsp; this &nbsp; structure &nbsp;<br>
&nbsp; HD_ITEM &nbsp; hi; &nbsp;<br>
&nbsp; hi.mask &nbsp; = &nbsp; HDI_WIDTH; // &nbsp; We &nbsp; want &nbsp; the &nbsp; column &nbsp; width. &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; // &nbsp; We &nbsp; keep &nbsp; a &nbsp; running &nbsp; sum &nbsp; of &nbsp; the &nbsp; horizontal &nbsp; location &nbsp;<br>
&nbsp; // &nbsp; of &nbsp; each &nbsp; column's &nbsp; divider. &nbsp;<br>
&nbsp; int &nbsp; dividerLocations &nbsp; = &nbsp; 0; &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; // &nbsp; The &nbsp; amount &nbsp; of &nbsp; space &nbsp; around &nbsp; the &nbsp; dividor &nbsp; inside &nbsp; of &nbsp; which &nbsp; one &nbsp; &nbsp;<br>
&nbsp; // &nbsp; can &nbsp; begin &nbsp; the &nbsp; dragging &nbsp; operation &nbsp; is &nbsp; equal &nbsp; to &nbsp; the &nbsp; width &nbsp; of &nbsp; &nbsp;<br>
&nbsp; // &nbsp; the &nbsp; cursor, &nbsp; centered &nbsp; at &nbsp; the &nbsp; dividor. &nbsp; &nbsp; So &nbsp; we &nbsp; need &nbsp; to &nbsp; trap &nbsp; &nbsp;<br>
&nbsp; // &nbsp; the &nbsp; cursor &nbsp; a &nbsp; distance &nbsp; of &nbsp; half &nbsp; the &nbsp; cursor &nbsp; width &nbsp; to &nbsp; each &nbsp; &nbsp;<br>
&nbsp; // &nbsp; side &nbsp; of &nbsp; the &nbsp; dividor. &nbsp;<br>
&nbsp; int &nbsp; dragWidth &nbsp; = &nbsp; GetSystemMetrics( &nbsp; SM_CXCURSOR &nbsp; ); &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; // &nbsp; Since &nbsp; we &nbsp; have &nbsp; no &nbsp; need &nbsp; to &nbsp; apply &nbsp; this &nbsp; test &nbsp; for &nbsp; columns &nbsp; for &nbsp; which &nbsp; &nbsp;<br>
&nbsp; // &nbsp; we &nbsp; want &nbsp; to &nbsp; enable &nbsp; dragging, &nbsp; we &nbsp; do &nbsp; not &nbsp; need &nbsp; to &nbsp; go &nbsp; beyond &nbsp; the &nbsp; last &nbsp; &nbsp;<br>
&nbsp; // &nbsp; column &nbsp; for &nbsp; which &nbsp; we &nbsp; want &nbsp; to &nbsp; disable &nbsp; dragging &nbsp; in &nbsp; our &nbsp; 'for &nbsp; loop'. &nbsp;<br>
&nbsp; BOOL &nbsp; allowDrag &nbsp; = &nbsp; TRUE; &nbsp;<br>
&nbsp; for &nbsp; (int &nbsp; i &nbsp; = &nbsp; 0; &nbsp; i &nbsp; &lt; &nbsp; 4; &nbsp; ++i) &nbsp; { &nbsp;<br>
&nbsp; GetItem(i, &nbsp; &amp;hi); &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; // &nbsp; hi.cxy &nbsp; contains &nbsp; the &nbsp; width &nbsp; of &nbsp; the &nbsp; i'th &nbsp; column. &nbsp;<br>
&nbsp; dividerLocations &nbsp; += &nbsp; hi.cxy; &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; // &nbsp; Here &nbsp; is &nbsp; where &nbsp; we &nbsp; place &nbsp; the &nbsp; indexes &nbsp; for &nbsp; the &nbsp; columns &nbsp; &nbsp;<br>
&nbsp; // &nbsp; for &nbsp; which &nbsp; we &nbsp; want &nbsp; to &nbsp; disable &nbsp; dragging. &nbsp;<br>
&nbsp; if &nbsp; (i &nbsp; == &nbsp; 0 &nbsp; || &nbsp;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; i &nbsp; == &nbsp; 2 &nbsp; || &nbsp;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; i &nbsp; == &nbsp; 3) &nbsp;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if &nbsp; (point.x &nbsp; &gt; &nbsp; dividerLocations &nbsp; - &nbsp; dragWidth/2 &nbsp; &amp;&amp; &nbsp;<br>
&nbsp; &nbsp; &nbsp; point.x &nbsp; &lt; &nbsp; dividerLocations &nbsp; + &nbsp; dragWidth/2) &nbsp;<br>
&nbsp; allowDrag &nbsp; = &nbsp; FALSE; &nbsp;<br>
&nbsp; } &nbsp;<br>
&nbsp; &nbsp;<br>
&nbsp; return &nbsp; allowDrag; &nbsp;<br>
&nbsp; } &nbsp; ]]></description>
		<eb:creationDate>2008-01-29 11:08:19</eb:creationDate>
		<eb:modificationDate></eb:modificationDate>
    </item>
    <item>
		<title><![CDATA[ VC小技巧20个 ]]></title>
		<link>http://blog.tom.com/hithink2006/article/1290.html</link>
		<description><![CDATA[ 一、打开CD-ROM<br>
mciSendString("Set&nbsp;cdAudio&nbsp;door&nbsp;open&nbsp;wait",NULL,0,NULL);<br>
<br>
二、关闭CD_ROM<br>
mciSendString("Set&nbsp;cdAudio&nbsp;door&nbsp;closed&nbsp;wait",NULL,0,NULL);<br>
<br>
三、关闭计算机<br>
OSVERSIONINFO&nbsp;OsVersionInfo;&nbsp;//包含操作系统版本信息的数据结构<br>
OsVersionInfo.dwOSVersionInfoSize&nbsp;=&nbsp;sizeof(OSVERSIONINFO);<br>
GetVersionEx(&amp;OsVersionInfo);&nbsp;//获取操作系统版本信息<br>
if(OsVersionInfo.dwPlatformId&nbsp;==&nbsp;VER_PLATFORM_WIN32_WINDOWS)<br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;//Windows98,调用ExitWindowsEx()函数重新启动计算机<br>
&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;dwReserved;<br>
&nbsp;&nbsp;&nbsp;&nbsp;ExitWindowsEx(EWX_REBOOT,dwReserved);&nbsp;//可以改变第一个参数，实现注销用户、&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;//关机、关闭电源等操作<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;退出前的一些处理程序<br>
}<br>
<br>
四、重启计算机<br>
typedef&nbsp;int&nbsp;(CALLBACK&nbsp;*SHUTDOWNDLG)(int);&nbsp;//显示关机对话框函数的指针<br>
HINSTANCE&nbsp;hInst&nbsp;=&nbsp;LoadLibrary("shell32.dll");&nbsp;//装入shell32.dll<br>
SHUTDOWNDLG&nbsp;ShutDownDialog;&nbsp;//指向shell32.dll库中显示关机对话框函数的指针<br>
if(hInst&nbsp;!=&nbsp;NULL)<br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;//获得函数的地址并调用之<br>
&nbsp;&nbsp;&nbsp;&nbsp;ShutDownDialog&nbsp;=&nbsp;(SHUTDOWNDLG)GetProcAddress(hInst,(LPSTR)60);<br>
&nbsp;&nbsp;&nbsp;&nbsp;(*ShutDownDialog)(0);<br>
}<br>
<br>
五、枚举所有字体<br>
LOGFONT&nbsp;lf;<br>
lf.lfCharSet&nbsp;=&nbsp;DEFAULT_CHARSET;&nbsp;//&nbsp;Initialize&nbsp;the&nbsp;LOGFONT&nbsp;structure<br>
strcpy(lf.lfFaceName,"");<br>
CClientDC&nbsp;dc&nbsp;(this);<br>
<br>
//Enumerate&nbsp;the&nbsp;font&nbsp;families<br>
::EnumFontFamiliesEx((HDC)&nbsp;dc,&amp;lf,<br>
(FONTENUMPROC)&nbsp;EnumFontFamProc,(LPARAM)&nbsp;this,0);<br>
<br>
//枚举函数<br>
int&nbsp;CALLBACK&nbsp;EnumFontFamProc(LPENUMLOGFONT&nbsp;lpelf,LPNEWTEXTMETRIC&nbsp;lpntm,DWORD&nbsp;nFontType,long&nbsp;lparam)<br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Create&nbsp;a&nbsp;pointer&nbsp;to&nbsp;the&nbsp;dialog&nbsp;window<br>
&nbsp;&nbsp;&nbsp;&nbsp;CDay7Dlg*&nbsp;pWnd&nbsp;=&nbsp;(CDay7Dlg*)&nbsp;lparam;<br>
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;add&nbsp;the&nbsp;font&nbsp;name&nbsp;to&nbsp;the&nbsp;list&nbsp;box<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;pWnd&nbsp;-&gt;m_ctlFontList.AddString(lpelf&nbsp;-&gt;elfLogFont.lfFaceName);<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Return&nbsp;1&nbsp;to&nbsp;continue&nbsp;font&nbsp;enumeration<br>
&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;1;<br>
}<br>
其中m_ctlFontList是一个列表控件变量<br>
<br>
六、一次只运行一个程序实例，如果已运行则退出<br>
if(&nbsp;FindWindow(NULL,"程序标题"))&nbsp;exit(0);<br>
<br>
七、得到当前鼠标所在位置<br>
CPoint&nbsp;pt;<br>
GetCursorPos(&amp;pt);&nbsp;//得到位置<br>
<br>
八、上下文菜单事件触发事件：OnContextMenu事件<br>
<br>
九、显示和隐藏程序菜单<br>
CWnd&nbsp;*pWnd=AfxGetMainWnd();&nbsp;<br>
if(b_m)&nbsp;//隐藏菜单<br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;pWnd-&gt;SetMenu(NULL);<br>
&nbsp;&nbsp;&nbsp;&nbsp;pWnd-&gt;DrawMenuBar();<br>
&nbsp;&nbsp;&nbsp;&nbsp;b_m=false;<br>
}<br>
else<br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;CMenu&nbsp;menu;<br>
&nbsp;&nbsp;&nbsp;&nbsp;menu.LoadMenu(IDR_MAINFRAME);&nbsp;////显示菜单&nbsp;也可改变菜单项<br>
&nbsp;&nbsp;&nbsp;&nbsp;pWnd-&gt;SetMenu(&amp;menu);<br>
&nbsp;&nbsp;&nbsp;&nbsp;pWnd-&gt;DrawMenuBar();<br>
&nbsp;&nbsp;&nbsp;&nbsp;b_m=true;<br>
&nbsp;&nbsp;&nbsp;&nbsp;menu.Detach();<br>
}<br>
<br>
十、获取可执行文件的图标<br>
HICON&nbsp;hIcon=::ExtractIcon(AfxGetInstanceHandle(),_T("NotePad.exe"),0);<br>
if&nbsp;(hIcon&nbsp;&amp;&amp;hIcon!=(HICON)-1)<br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;pDC-&gt;DrawIcon(10,10,hIcon);<br>
}<br>
DestroyIcon(hIcon);<br>
&nbsp;<br>
&nbsp;<br>
十一、窗口自动靠边程序演示<br>
BOOL&nbsp;AdjustPos(CRect*&nbsp;lpRect)<br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;//自动靠边<br>
&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;iSX=GetSystemMetrics(SM_CXFULLSCREEN);<br>
&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;iSY=GetSystemMetrics(SM_CYFULLSCREEN);<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;RECT&nbsp;rWorkArea;<br>
&nbsp;&nbsp;&nbsp;&nbsp;BOOL&nbsp;bResult&nbsp;=&nbsp;SystemParametersInfo(SPI_GETWORKAREA,&nbsp;sizeof(RECT),&nbsp;&amp;rWorkArea,&nbsp;0);&nbsp;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;CRect&nbsp;rcWA;<br>
&nbsp;&nbsp;&nbsp;&nbsp;if(!bResult)<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//如果调用不成功就利用GetSystemMetrics获取屏幕面积<br>
rcWA=CRect(0,0,iSX,iSY);<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
&nbsp;&nbsp;&nbsp;&nbsp;else<br>
rcWA=rWorkArea;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;iX=lpRect-&gt;left;<br>
&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;iY=lpRect-&gt;top;<br>
&nbsp;&nbsp;&nbsp;&nbsp;if(iX&nbsp;&lt;&nbsp;rcWA.left&nbsp;+&nbsp;DETASTEP&nbsp;&amp;&amp;&nbsp;iX!=rcWA.left)<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//调整左<br>
//pWnd-&gt;SetWindowPos(NULL,rcWA.left,iY,0,0,SWP_NOSIZE);<br>
lpRect-&gt;OffsetRect(rcWA.left-iX,0);<br>
AdjustPos(lpRect);<br>
return&nbsp;TRUE;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
&nbsp;&nbsp;&nbsp;&nbsp;if(iY&nbsp;&lt;&nbsp;rcWA.top&nbsp;+&nbsp;DETASTEP&nbsp;&amp;&amp;&nbsp;iY!=rcWA.top)<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
//调整上<br>
//pWnd-&gt;SetWindowPos(NULL&nbsp;,iX,rcWA.top,0,0,SWP_NOSIZE);<br>
lpRect-&gt;OffsetRect(0,rcWA.top-iY);<br>
AdjustPos(lpRect);<br>
return&nbsp;TRUE;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
&nbsp;&nbsp;&nbsp;&nbsp;if(iX&nbsp;+&nbsp;lpRect-&gt;Width()&nbsp;&gt;&nbsp;rcWA.right&nbsp;-&nbsp;DETASTEP&nbsp;&amp;&amp;&nbsp;iX&nbsp;!=rcWA.right-lpRect-&gt;Width())<br>
&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;<br>
//调整右<br>
//pWnd-&gt;SetWindowPos(NULL&nbsp;,rcWA.right-rcW.Width(),iY,0,0,SWP_NOSIZE);<br>
lpRect-&gt;OffsetRect(rcWA.right-lpRect-&gt;right,0);<br>
AdjustPos(lpRect);<br>
return&nbsp;TRUE;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
&nbsp;&nbsp;&nbsp;&nbsp;if(iY&nbsp;+&nbsp;lpRect-&gt;Height()&nbsp;&gt;&nbsp;rcWA.bottom&nbsp;-&nbsp;DETASTEP&nbsp;&amp;&amp;&nbsp;iY&nbsp;!=rcWA.bottom-lpRect-&gt;Height())<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
//调整下<br>
&nbsp;&nbsp;&nbsp;&nbsp; //pWnd-&gt;SetWindowPos(NULL&nbsp;,iX,rcWA.bottom-rcW.Height(),0,0,SWP_NOSIZE);<br>
lpRect-&gt;OffsetRect(0,rcWA.bottom-lpRect-&gt;bottom);<br>
return&nbsp;TRUE;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;FALSE;<br>
}<br>
//然后在ONMOVEING事件中使用所下过程调用<br>
CRect&nbsp;r=*pRect;<br>
AdjustPos(&amp;r);<br>
*pRect=(RECT)r;<br>
<br>
十二、给系统菜单添加一个菜单项<br>
给系统菜单添加一个菜单项需要进行下述三个步骤：<br>
首先，使用Resource&nbsp;Symbols对话（在View菜单中选择Resource&nbsp;Symbols．．．可以显示该对话）定义菜单项ID，该ID应大于<br>
<br>
0x0F而小于0xF000；<br>
其次，调用CWnd::GetSystemMenu获取系统菜单的指针并调用CWnd::&nbsp;Appendmenu将菜单项添加到菜单中。下例给系统菜单添加<br>
<br>
两个新的菜单项。<br>
int&nbsp;CMainFrame::&nbsp;OnCreate&nbsp;(LPCREATESTRUCT&nbsp;lpCreateStruct)<br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;…<br>
&nbsp;&nbsp;&nbsp;&nbsp;//Make&nbsp;sure&nbsp;system&nbsp;menu&nbsp;item&nbsp;is&nbsp;in&nbsp;the&nbsp;right&nbsp;range.<br>
&nbsp;&nbsp;&nbsp;&nbsp;ASSERT(IDM_MYSYSITEM&lt;0xF000);<br>
&nbsp;&nbsp;&nbsp;&nbsp;//Get&nbsp;pointer&nbsp;to&nbsp;system&nbsp;menu.<br>
&nbsp;&nbsp;&nbsp;&nbsp;CMenu*&nbsp;pSysMenu=GetSystemMenu(FALSE);<br>
&nbsp;&nbsp;&nbsp;&nbsp;ASSERT_VALID(pSysMenu);<br>
&nbsp;&nbsp;&nbsp;&nbsp;//Add&nbsp;a&nbsp;separator&nbsp;and&nbsp;our&nbsp;menu&nbsp;item&nbsp;to&nbsp;system&nbsp;menu.<br>
&nbsp;&nbsp;&nbsp;&nbsp;CString&nbsp;StrMenuItem(_T&nbsp;("New&nbsp;menu&nbsp;item"));<br>
&nbsp;&nbsp;&nbsp;&nbsp;pSysMenu-&gt;AppendMenu(MF_SEPARATOR);<br>
&nbsp;&nbsp;&nbsp;&nbsp;pSysMenu-&gt;AppendMenu(MF_STRING,&nbsp;IDM_MYSYSITEM,&nbsp;StrMenuItem);<br>
&nbsp;&nbsp;&nbsp;&nbsp;…<br>
}<br>
<br>
13、运行其它程序<br>
//运行EMAIL或网址<br>
char&nbsp;szMailAddress[80];&nbsp;<br>
strcpy(szMailAddress,"mailto:netvc@21cn.com");<br>
ShellExecute(NULL,&nbsp;"open",&nbsp;szMailAddress,&nbsp;NULL,&nbsp;NULL,&nbsp;SW_SHOWNORMAL);<br>
<br>
//2、运行可执行程序<br>
WinExec("notepad.exe",SW_SHOW);&nbsp;//运行计事本<br>
<br>
14、动态增加或删除菜单<br>
(1)、&nbsp;增加菜单<br>
//添加<br>
CMenu&nbsp;*mainmenu;&nbsp;<br>
mainmenu=AfxGetMainWnd()-&gt;GetMenu();&nbsp;//得到主菜单<br>
(mainmenu-&gt;GetSubMenu&nbsp;(0))-&gt;AppendMenu&nbsp;(MF_SEPARATOR);//添加分隔符<br>
(mainmenu-&gt;GetSubMenu&nbsp;(0))-&gt;AppendMenu(MF_STRING,ID_APP_ABOUT,_T("Always&nbsp;on&nbsp;&amp;Top"));&nbsp;//添加新的菜单项<br>
DrawMenuBar();&nbsp;//重画菜单<br>
<br>
(2)、&nbsp;删除菜单<br>
//删除<br>
CMenu&nbsp;*mainmenu;&nbsp;<br>
mainmenu=AfxGetMainWnd()-&gt;GetMenu();&nbsp;//得到主菜单<br>
CString&nbsp;str&nbsp;;<br>
for(int&nbsp;i=(mainmenu-&gt;GetSubMenu&nbsp;(0))-&gt;GetMenuItemCount()-1;i&gt;=0;i--)&nbsp;//取得菜单的项数。<br>
{&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;(mainmenu-&gt;GetSubMenu&nbsp;(0))-&gt;GetMenuString(i,str,MF_BYPOSITION);&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;//将指定菜单项的标签拷贝到指定的缓冲区。MF_BYPOSITION的解释见上。&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;if(str=="Always&nbsp;on&nbsp;&amp;Top")&nbsp;//如果是刚才我们增加的菜单项，则删除。&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;<br>
(mainmenu-&gt;GetSubMenu&nbsp;(0))-&gt;DeleteMenu(i,MF_BYPOSITION);&nbsp;<br>
&nbsp; break;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
}<br>
<br>
15、测试ALT键是否按下：<br>
GetKeyState(VK_MENU);<br>
GetAlt();<br>
16、检查是否按下鼠标左键<br>
if((nFlags&amp;MK_LBUTTON)==MK_LBUTTON)<br>
<br>
<br>
17、检查键盘输入&nbsp;<br>
在OnKeyDown中的参数nChar是一个数值，当显示的时候，需要转换成字符，使用如下的命令：<br>
char&nbsp;lsChar;<br>
lsChar=char(nChar);<br>
if(lsChar=='A');<br>
{<br>
.......<br>
}<br>
<br>
18、调用另一个函数::GetKeyState()，用一个特定的键代码来确定法键是否被按下。如果::GetKeyState函数的返回值是负的，表示该键被按下。如果返回值是非负的，表示该留未被按下。例如：如果要确定shift键是否被按下，可以使用下面的代码：<br>
if(::GetKeyState(VK_SHIFT)&lt;O)<br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;AfxMessageBox("shift&nbsp;is&nbsp;pressed");<br>
}<br>
<br>
19.如何在编程的过程中随时结束应用程序(常规)&nbsp;<br>
1)需要向窗口发送&nbsp;WM_CLOSE/WM_QUIT消息,<br>
调用&nbsp;CWnd::OnClose成员函数并允许对用户提示是否保存修改过的数据.<br>
AfxGetMainWnd()-&gt;SendMessage(WM_CLOSE);&nbsp;//别忘了先得到当前窗口的指针<br>
2)使用函数：&nbsp;void&nbsp;PostQuitMessage(&nbsp;int&nbsp;nExitCode&nbsp;//&nbsp;exit&nbsp;code&nbsp;);<br>
3)使用标准函数：void&nbsp;exit(&nbsp;int&nbsp;status&nbsp;);&nbsp;//尽量不要在MFC中使用<br>
<br>
20.得到屏幕的尺寸大小<br>
HWND&nbsp;hWnd;<br>
CRect&nbsp;Rect;<br>
hWnd&nbsp;=&nbsp;::GetDesktopWindow();<br>
::GetClientRect(hWnd,&nbsp;&amp;Rect);<br>
<br>
//---------------------------------------------------------<br>
如何查询和设置系统参数<br>
&nbsp;&nbsp;&nbsp;&nbsp;在Windows&nbsp;3.1&nbsp;SDK中介绍过SDK函数SystemParametersInfo，调用该函数可以查询和设置系统参数，诸如按键的重复速率设置、鼠标双击延迟时间、图标字体以及桌面覆盖位图等等。&nbsp;&nbsp;<br>
//Create&nbsp;a&nbsp;font&nbsp;that&nbsp;is&nbsp;used&nbsp;for&nbsp;icon&nbsp;titles.&nbsp;&nbsp;<br>
LOGFONT&nbsp;stFont;&nbsp;&nbsp;::&nbsp;SystemParametersInfo&nbsp;(SPIF_GETICONTITLELOGFONT,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sizeof&nbsp;(LOGFONT),&nbsp;&amp;stFont,&nbsp;SPIF_SENDWININICHANGE);&nbsp;&nbsp;<br>
m_font.CreateFontIndirect&nbsp;(&amp;stFont);&nbsp;&nbsp;//Change&nbsp;the&nbsp;wallpaper&nbsp;to&nbsp;leaves.bmp.&nbsp;&nbsp;<br>
::&nbsp;SystemParametersInfo&nbsp;(SPI_SETDESKWALLPAPER,&nbsp;0,&nbsp;_T("forest.bmp"),SPIF_UPDATEINIFILE);&nbsp;&nbsp;<br>
<br>
//---------------------------------------------------------<br>
如何使用一个预定义的Windows光标<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;调用CWinApp::&nbsp;LoadStandardCursor并传送光标标识符。<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BOOL&nbsp;CSampleDialog::&nbsp;OnSetCursor&nbsp;(CWnd*&nbsp;pWnd,&nbsp;UINT&nbsp;nHitTest,&nbsp;UINT&nbsp;message)&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//Display&nbsp;wait&nbsp;cursor&nbsp;if&nbsp;busy.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
if&nbsp;(m_bBusy)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
SetCursor&nbsp;(AfxGetApp&nbsp;()&nbsp;-&gt;LoadStandardCursor&nbsp;(IDC_WAIT));&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
return&nbsp;TRUE;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
return&nbsp;CDialog::&nbsp;OnSetCursor&nbsp;(pWnd.&nbsp;nHitTest,message);&nbsp;&nbsp;}
<p>&nbsp;</p>
<hr>
<font color="#999999" face="Arial, Helvetica, sans-serif" size="2">CSDN VC编程经验总结</font> ]]></description>
		<eb:creationDate>2008-01-29 09:47:11</eb:creationDate>
		<eb:modificationDate></eb:modificationDate>
    </item>
    <item>
		<title><![CDATA[ 用VC++在基于对话框的程序中动态更改光标 ]]></title>
		<link>http://blog.tom.com/hithink2006/article/1289.html</link>
		<description><![CDATA[ 在很多应用<a href="http://dev.yesky.com/" class="bluekey" target="_blank">程序</a>中都提供了动态改变光标的功能，例如，对于我们常用的Word字处理<a href="http://product.yesky.com/software/" class="bluekey" target="_blank">软件</a>，当在文档中输入邮件地址后，每当<a href="http://product.yesky.com/catalog/212/" class="bluekey" target="_blank">鼠标</a>进入邮件地址区域，鼠标的形状就由箭头改变为手指形状。本实例在一个基于对话框的程序中模拟上述功能，如果将鼠标移到对话框的按钮上（"OK"键和"Cancel"键），光标指针变为蓝色手指，如果将鼠标指针移到带下划线的超链接上，光标指针又变为另外一个Windows中常常使用的手指。程序编译运行后的效果如下图所示：<br>
<br>
<table align="center" border="0" width="90%">
<tbody>
<tr>
<td>
<div align="center"><img src="http://dev.yesky.com/imagelist/05/12/c8klbf435798.png" border="0"><br>
图一、动态改变程序的光标效果图</div>
</td>
</tr>
</tbody>
</table>
<br>
　　<b>一、实现方法</b><br>
<br>
　　Wndows编程中有两种方法改变光标，一种方法是当应用的主窗口类注册时，为WNDCLASS结构提供一个全程光标指针（HCURSOR），另外一种方法是在程序中处理WM_SETCURSOR消息来设置鼠标光标。标准的MFC应用程序使用第一种方法自动在主窗口注册时将光标指针设置为一个箭头。如果要改变光标指针，则可以通过在主窗口或子窗口中重载消息WM_SETCURSOR的处理函数来重新设置鼠标指针。下面的代码实现更改按钮上的光标：<br>
<br>
<table align="center" bgcolor="#E3E3E3" border="1" bordercolor="#CCCCCC" width="90%">
<tbody>
<tr>
<td>// handle WM_SETCURSOR in button class<br>
BOOL CMyButton::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT msg)<br>
{<br>
　::SetCursor(m_hMyCursor);<br>
　return TRUE;<br>
}</td>
</tr>
</tbody>
</table>
<br>
　　当用户将鼠标指针移到按钮上时，鼠标不被捕获，Windows发送一个WM_SETCURSOR消息到按钮。从上面OnSetCursor的代码中可以看到，它传递的第一个参数是窗口句柄（pWnd）-即鼠标指针所指的窗口，这里指的是按钮本身；OnSetCursor传递的第二个参数是nHitTest，这是一个鼠标点击测试代码（Mouse Hit-TestCodes），它以HTXXX开头，用于WM_NCHITTEST消息；OnSetCursor传递的第三个参数是触发事件的鼠标消息，例如它的值可以为WM_MOUSEMOVE。WM_SETCURSOR是专门用来设置鼠标指针的消息，当设置了鼠标指针以后，应该让它返回TRUE以防止Windows再作缺省处理。<br>
<br>
　　WM_SETCURSOR的处理机制是这样的，如果有父窗口的话，缺省的窗口过程首先发送WM_SETCURSOR消息到父窗口，如果父窗口处理WM_SETCURSOR消息（即返回TRUE），则Windows不再作任何多余的事情，处理完消息便结束。如果父窗口不处理WM_SETCURSOR消息（即返回FALSE），Windows让子窗口来处理WM_SETCURSOR，如果子窗口也不做任何处理（返回FALSE），Windows使用全程光标指针，如果没有全程光标指针，则使用箭头指针。<br>
<br>
　　如果你在程序中要是使用动态光标指针，你必须决定是在子窗口处理WM_SETCURSOR消息还是在父窗口中处理WM_SETCURSOR消息。两种方法各有利弊，根据具体情况而定。一般总是让对象决定它们自己的行为属性-也就是说最好在子窗口中做处理。本例中的子窗口即静态控件。这就要派生一个新的CStatic类的子类，该类有自己的消息映射及其消息处理过程。<br>
<br>
　　CWnd::SetCursor（）函数使用起来比较简单，只要将待选择的鼠标的句柄（装载鼠标函数为：LoadIcon（））作为该函数的参数就可以了。<br>
<br>
　　<b>二、编程步骤</b><br>
<br>
　　1、 启动Visual C++6.0，生成一个基于对话框的应用程序MyCursor，并添加光标资源IDC_MYHAND；<br>
<br>
　　2、 使用Class Wizard添加CHyperlink、StatLink类定义；<br>
<br>
　　3、 在对话框类中定义下列变量HICON m_hIcon、 CStaticLink m_wndLink1、CStaticLink m_wndLink2、HCURSOR m_hButtonCursor；<br>
<br>
　　4、 使用Class Wizard为对话框类添加WM_SETCURSOR消息处理函数；<br>
<br>
　　5、 添加代码，编译运行程序。<br>
<b>三、程序代码</b><br>
<br>
<table align="center" bgcolor="#E3E3E3" border="1" bordercolor="#CCCCCC" width="90%">
<tbody>
<tr>
<td>////////////////////////////////////////////////////////////////////////////<br>
#ifndef _HYPRILNK_H<br>
#define _HYPRILNK_H<br>
// Simple text hyperlink derived from CString<br>
class CHyperlink : public CString {<br>
public:<br>
　CHyperlink(LPCTSTR lpLink = NULL) : CString(lpLink) { }<br>
　~CHyperlink() { }<br>
　const CHyperlink&amp; operator=(LPCTSTR lpsz) {<br>
　　CString::operator=(lpsz);<br>
　　return *this;<br>
　}<br>
　operator LPCTSTR() {<br>
　　return CString::operator LPCTSTR();<br>
　}<br>
　virtual HINSTANCE Navigate() {<br>
　　return IsEmpty() ? NULL :<br>
　　ShellExecute(0, _T("open"), *this, 0, 0, SW_SHOWNORMAL);<br>
　}<br>
};<br>
#endif<br>
/////////////////////////////////////////////////////////////////////////////////<br>
#ifndef _STATLINK_H<br>
#define _STATLINK_H<br>
#include "HyprLink.h"<br>
class CStaticLink : public CStatic {<br>
public:<br>
　DECLARE_DYNAMIC(CStaticLink)<br>
　CStaticLink(LPCTSTR lpText = NULL, BOOL bDeleteOnDestroy=FALSE);<br>
　~CStaticLink() { }<br>
　// Hyperlink contains URL/filename. If NULL, I will use the window text.<br>
　// (GetWindowText) to get the target.<br>
　CHyperlink m_link;<br>
　COLORREF m_color;<br>
　// Default colors you can change<br>
　// These are global, so they're the same for all links.<br>
　static COLORREF g_colorUnvisited;<br>
　static COLORREF g_colorVisited;<br>
　static HCURSOR g_hCursorLink;<br>
protected:<br>
　CFont m_font; // underline font for text control<br>
　BOOL m_bDeleteOnDestroy; // delete object when window destroyed?<br>
　virtual void PostNcDestroy();<br>
　// message handlers<br>
　DECLARE_MESSAGE_MAP()<br>
　afx_msg UINT OnNcHitTest(CPoint point);<br>
　afx_msg HBRUSH CtlColor(CDC* pDC, UINT nCtlColor);<br>
　afx_msg void OnLButtonDown(UINT nFlags, CPoint point);<br>
　afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);<br>
};<br>
#endif _STATLINK_H<br>
/////////////////////////////////////////////////////////////////////////<br>
#include "StdAfx.h"<br>
#include "StatLink.h"<br>
#ifdef _DEBUG<br>
#define new DEBUG_NEW<br>
#undef THIS_FILE<br>
static char THIS_FILE[] = __FILE__;<br>
#endif<br>
COLORREF CStaticLink::g_colorUnvisited = RGB(0,0,255); // blue<br>
COLORREF CStaticLink::g_colorVisited = RGB(128,0,128); // purple<br>
HCURSOR CStaticLink::g_hCursorLink = NULL;<br>
IMPLEMENT_DYNAMIC(CStaticLink, CStatic)<br>
BEGIN_MESSAGE_MAP(CStaticLink, CStatic)<br>
ON_WM_NCHITTEST()<br>
ON_WM_CTLCOLOR_REFLECT()<br>
ON_WM_LBUTTONDOWN()<br>
ON_WM_SETCURSOR()<br>
END_MESSAGE_MAP()<br>
///////////////////<br>
// Constructor sets default colors = blue/purple.<br>
// bDeleteOnDestroy is used internally by PixieLib in CPixieDlg.<br>
CStaticLink::CStaticLink(LPCTSTR lpText, BOOL bDeleteOnDestroy)<br>
{<br>
　m_link = lpText; // link text (NULL ==&gt; window text)<br>
　m_color = g_colorUnvisited; // not visited yet<br>
　m_bDeleteOnDestroy = bDeleteOnDestroy; // delete object with window?<br>
}<br>
//////////////////<br>
// Normally, a static control does not get mouse events unless it has<br>
// SS_NOTIFY. This achieves the same effect as SS_NOTIFY, but it's fewer<br>
// lines of code and more reliable than turning on SS_NOTIFY in OnCtlColor<br>
// because Windows doesn't send WM_CTLCOLOR to bitmap static controls.<br>
//<br>
UINT CStaticLink::OnNcHitTest(CPoint point)<br>
{<br>
　return HTCLIENT;<br>
}<br>
<br>
//////////////////<br>
// Handle reflected WM_CTLCOLOR to set custom control color.<br>
// For a text control, use visited/unvisited colors and underline font.<br>
// For non-text controls, do nothing. Also ensures SS_NOTIFY is on.<br>
//<br>
HBRUSH CStaticLink::CtlColor(CDC* pDC, UINT nCtlColor)<br>
{<br>
　ASSERT(nCtlColor == CTLCOLOR_STATIC);<br>
　DWORD dwStyle = GetStyle();<br>
<br>
　HBRUSH hbr = NULL;<br>
　if ((dwStyle &amp; 0xFF) &lt;= SS_RIGHT) {<br>
<br>
　　// this is a text control: set up font and colors<br>
　　if (!(HFONT)m_font) {<br>
　　　// first time init: create font<br>
　　　LOGFONT lf;<br>
　　　GetFont()-&gt;GetObject(sizeof(lf), &amp;lf);<br>
　　　lf.lfUnderline = TRUE;<br>
　　　m_font.CreateFontIndirect(&amp;lf);<br>
　　}<br>
　　// use underline font and visited/unvisited colors<br>
　　pDC-&gt;SelectObject(&amp;m_font);<br>
　　pDC-&gt;SetTextColor(m_color);<br>
　　pDC-&gt;SetBkMode(TRANSPARENT);<br>
　　// return hollow brush to preserve parent background color<br>
　　hbr = (HBRUSH)::GetStockObject(HOLLOW_BRUSH);<br>
　}<br>
　return hbr;<br>
}<br>
/////////////////<br>
// Handle mouse click: navigate link<br>
//<br>
void CStaticLink::OnLButtonDown(UINT nFlags, CPoint point)<br>
{<br>
　if (m_link.IsEmpty()) {<br>
　　// no link: try to load from resource string or window text<br>
　　m_link.LoadString(GetDlgCtrlID()) || (GetWindowText(m_link),1);<br>
　　if (m_link.IsEmpty())<br>
　　return;<br>
　}<br>
　// Call ShellExecute to run the file.<br>
　// For an URL, this means opening it in the browser.<br>
　//<br>
　HINSTANCE h = m_link.Navigate();<br>
　if ((UINT)h &gt; 32) { // success!<br>
　　m_color = g_colorVisited; // change color<br>
　　Invalidate(); // repaint<br>
　} else {<br>
　　MessageBeep(0); // unable to execute file!<br>
　　TRACE(_T("*** WARNING: CStaticLink: unable to navigate link %s"),(LPCTSTR)m_link);<br>
　}<br>
}<br>
<br>
//////////////////<br>
// Set "hand" cursor to cue user that this is a link. If app has not set<br>
// g_hCursorLink, then try to get the cursor from winhlp32.exe,<br>
// resource 106, which is a pointing finger. This is a bit of a kludge,<br>
// but it works.<br>
//<br>
BOOL CStaticLink::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)<br>
{<br>
　if (g_hCursorLink == NULL) {<br>
　　static bTriedOnce = FALSE;<br>
　　if (!bTriedOnce) {<br>
　　　CString windir;<br>
　　　GetWindowsDirectory(windir.GetBuffer(MAX_PATH), MAX_PATH);<br>
　　　windir.ReleaseBuffer();<br>
　　　windir += _T("\winhlp32.exe");<br>
　　　HMODULE hModule = LoadLibrary(windir);<br>
　　　if (hModule) {<br>
　　　　g_hCursorLink = CopyCursor(::LoadCursor(hModule, MAKEINTRESOURCE(106)));<br>
　　　}<br>
　　　FreeLibrary(hModule);<br>
　　　bTriedOnce = TRUE;<br>
　　}<br>
　}<br>
　if (g_hCursorLink) {<br>
　　::SetCursor(g_hCursorLink);<br>
　　return TRUE;<br>
　}<br>
　return FALSE;<br>
}<br>
<br>
//////////////////<br>
// Normally, a control class is not destoyed when the window is;<br>
// however, CPixieDlg creates static controls with "new" instead of<br>
// as class members, so it's convenient to allow the option of destroying<br>
// object with window. In applications where you want the object to be<br>
// destoyed along with the window, you can call constructor with<br>
// bDeleteOnDestroy=TRUE.<br>
//<br>
void CStaticLink::PostNcDestroy()<br>
{<br>
　if (m_bDeleteOnDestroy)<br>
　delete this;<br>
}<br>
//////////////////////////////////////////////////////////////////////////////<br>
<br>
#include "stdafx.h"<br>
#include "resource.h"<br>
#include "TraceWin.h"<br>
#include "StatLink.h"<br>
#ifdef _DEBUG<br>
#define new DEBUG_NEW<br>
#undef THIS_FILE<br>
static char THIS_FILE[] = __FILE__;<br>
#endif<br>
class CMyDialog : public CDialog {<br>
public:<br>
　CMyDialog(CWnd* pParent = NULL);<br>
　~CMyDialog();<br>
　//protected:<br>
private:<br>
　HICON m_hIcon;<br>
　CStaticLink m_wndLink1; // web links<br>
　CStaticLink m_wndLink2;<br>
　// the button cursor<br>
　HCURSOR m_hButtonCursor;<br>
　virtual BOOL OnInitDialog();<br>
　afx_msg void OnPaint();<br>
　afx_msg HCURSOR OnQueryDragIcon();<br>
　afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT msg);<br>
　DECLARE_MESSAGE_MAP()<br>
};<br>
BEGIN_MESSAGE_MAP(CMyDialog, CDialog)<br>
ON_WM_PAINT()<br>
ON_WM_QUERYDRAGICON()<br>
ON_WM_SETCURSOR()<br>
END_MESSAGE_MAP()<br>
<br>
CMyDialog::CMyDialog(CWnd* pParent /*=NULL*/)<br>
: CDialog(IDD_MYDIALOG, pParent)<br>
{}<br>
<br>
CMyDialog::~CMyDialog()<br>
{}<br>
<br>
//////////////////<br>
// Initialize dialog<br>
//<br>
BOOL CMyDialog::OnInitDialog()<br>
{<br>
　CDialog::OnInitDialog();<br>
　// set up hyperlinks<br>
　m_wndLink1.m_link = _T("http://www.vckbase.com");<br>
　m_wndLink2.m_link = _T("mailto:vckbase@public.hk.hi.cn");<br>
　m_wndLink1.SubclassDlgItem(IDC_PDURL, this);<br>
　m_wndLink2.SubclassDlgItem(IDC_MSDNURL, this);<br>
　// Set the icon for this dialog. The framework does this automatically<br>
　// when the application's main window is not a dialog<br>
　m_hIcon = AfxGetApp()-&gt;LoadIcon(IDR_MAINFRAME);<br>
　SetIcon(m_hIcon, TRUE); // Set big icon<br>
　SetIcon(m_hIcon, FALSE); // Set small icon<br>
　// load button cursor<br>
　m_hButtonCursor = AfxGetApp()-&gt;LoadCursor(IDC_MYHAND);<br>
　return TRUE; // return TRUE unless you set the focus to a control<br>
}<br>
<br>
//////////////////<br>
// Set cursor if mouse is over a button.<br>
//<br>
BOOL CMyDialog::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT msg)<br>
{<br>
　CString sClassName;<br>
　::GetClassName(pWnd-&gt;GetSafeHwnd(),sClassName.GetBuffer(80),80);<br>
　if (sClassName=="Button" &amp;&amp; m_hButtonCursor) {<br>
　　::SetCursor(m_hButtonCursor);<br>
　　return TRUE;<br>
　}<br>
　return CDialog::OnSetCursor(pWnd, nHitTest, msg);<br>
}</td>
</tr>
</tbody>
</table>
<br>
　　<b>四、小结</b><br>
<br>
　　本文不仅介绍了动态改变程序中的鼠标形状，还介绍了如何实现静态文本的超连接，读者朋友可以将这部分代码修改后应用到自己开放的应用程序中，例如在程序中添加自己的<a href="http://homepage.yesky.com/" class="bluekey" target="_blank">网页</a>和邮箱地址等，我想这一定是件很令人鼓舞的事情吧。<br> ]]></description>
		<eb:creationDate>2008-01-29 09:38:45</eb:creationDate>
		<eb:modificationDate></eb:modificationDate>
    </item>
</channel>
</rss>