第一個duilib程序--HelloWorld


duilib是一個windows下的皮膚庫,用win32寫的。。。

先看個效果圖吧:

這個圖片里有源代碼,右鍵保存下圖標,把后綴改為zip,即可。由於skin目錄下的圖片不便上傳,需要自己加入合適的圖片。

 

要使用duilib庫,必須先把庫導入,代碼如下:

 1 #include "xxx\UIlib.h" //xxx為UIlib.h的路徑
 2 using namespace Duilib; //Duilib為庫自定義的名字空間
 3 
 4 #ifdef _DEBUG
 5  #ifdef _UNICODE
 6   #pragma comment(lib, "xxx\Duilib_ud.lib")
 7  #else
 8   #pragma comment(lib, "xxx\Duilib_d.lib")
 9  #endif
10 #else
11  #ifdef _UNICODE
12   #progma comment(lib, "xxx\Duilib_u.lib")
13  #else
14   #progma comment(lib, "xxx\Duilib.lib")
15 #endif

 

使用duilib庫的程序和win32程序一樣也是從WinMain開始的。在WinMain函數中,一般是這樣做的:

1 CPaintManagerUI::SetInstance(hInstance);//將程序實例與皮膚繪制管理器掛鈎
2 CPaintMamagerUI::SetResourcePath(CPaintManagerUI::GetInstancePath() + TEXT("skin"));//設置皮膚庫的資源路徑,資源有圖片、xml文件等
3 CPaintManagerUI::SetResourceZip(/*路徑*/);//皮膚庫支持壓縮文件,這里指定壓縮文件路徑
4 //new一個類,這個類繼承自CWindowWnd類
5 //調用類的Create函數創建窗口,這里會發送WM_CREATE消息,而這個類一般會在HandleMessage函數中處理WM_CREATE消息
6 //創建完窗口后,可以調用該類的SetIcon(IDI_HW)函數來設置任務欄上顯示的圖標
7 //然后調用CPaintManagerUI::MessageLoop(),進入消息循環

在duilib中每個窗口均要定義一個CPaintManagerUI成員對象用來管理整個窗口的繪制。

duilib中的窗口均繼承自CWindowWnd類,在CWindowWnd類中有虛函數HandleMessage來處理Windows消息(如WM_CREATE、WM_SIZE等)。另外,如果你的窗口想要響應鼠標的點擊、編輯框內容改變等消息的話,可以把你的窗口類繼承INotify接口,這樣你的窗口上的一個按鈕被點擊了,可以在繼承自INotify接口的Notify函數中進行處理。

在自己定義的窗口類中一般這樣來處理HandleMessage:

 1 LRESULT CHelloWorld::HandleMessage( UINT uMsg, WPARAM wParam, LPARAM lParam )
 2 {
 3     LRESULT lRes = 0;//返回值
 4     BOOL bHandled = TRUE;//是否被處理了
 5     switch (uMsg)
 6     {
 7     case WM_CREATE:
 8         lRes = OnCreate(uMsg ,wParam, lParam, bHandled);
 9         break;
10     default:
11         bHandled = FALSE; break;
12     }
13     
14     if (bHandled) return lRes;
15     if (m_pm.MessageHandler(uMsg, wParam, lParam, lRes) != 0)//沒有處理,這傳送給窗口繪制管理器處理,Notify函數將會在這里的m_pm.MessageHandler函數中被調用
16         return lRes;
17     return CWindowWnd::HandleMessage(uMsg, wParam, lParam);//都不處理則有CWindowWnd處理
18 }

INotifyUI接口的Notify()由CPaintManagerUI::MessageHandler調用。繼承INotifyUI接口的類對象會被加入到CPaintManagerUI的m_aNotifiers數組中,而要加入m_aNotifiers數組一般由窗口類自己在OnCreate函數調用CPaintManagerUI的靜態方法AddNotifier將自己加入到m_aNotifiers中。

而在自己的窗口類的OnCreate函數中,通常調用m_pm.Init(m_hWnd)來把自己的窗口句柄與窗口繪制管理器掛接在一起,即用於向CPaintManagerUI提供窗口句柄及窗口上下文句柄。

 1 LRESULT CHelloWorld::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
 2 {
 3     m_pm.Init(m_hWnd);    // 把自己的窗口句柄與窗口繪制管理器掛接在一起
 4     CDialogBuilder builder;
 5     CControlUI* pRoot = builder.Create(TEXT("HelloWorld.xml"), (UINT)0, NULL, &m_pm); // 根據xml中的配置創建控件
 6     ASSERT(pRoot && "Failure to parse XML");
 7     m_pm.AttachDialog(pRoot); // 把這些控件繪制到本窗口上
 8     m_pm.AddNotifier(this);    // 把自己加入到CPaintManagerUI的m_aNotifiers數組中,用於處理Notify函數
 9     Init();
10     return 0;
11 
12 }

以上就是關於duilib程序的一個建立過程。


 

貼代碼先:

 1 // stdafx.h : 標准系統包含文件的包含文件,
 2 // 或是經常使用但不常更改的
 3 // 特定於項目的包含文件
 4 //
 5 
 6 #pragma once
 7 
 8 #define WIN32_LEAN_AND_MEAN             // 從 Windows 頭中排除極少使用的資料
 9 // Windows 頭文件:
10 #include <windows.h>
11 #include <objbase.h>
12 
13 // TODO: 在此處引用程序需要的其他頭文件
14 #include "..\..\DuiLib\UIlib.h"
15 
16 using namespace DuiLib;
17 
18 #ifdef _DEBUG
19 #   ifdef _UNICODE
20 #       pragma comment(lib, "..\\..\\bin\\DuiLib_ud.lib")
21 #   else
22 #       pragma comment(lib, "..\\..\\bin\\DuiLib_d.lib")
23 #   endif
24 #else
25 #   ifdef _UNICODE
26 #       pragma comment(lib, "..\\..\\bin\\DuiLib_u.lib")
27 #   else
28 #       pragma comment(lib, "..\\..\\bin\\DuiLib.lib")
29 #   endif
30 #endif
1 // stdafx.cpp : 只包括標准包含文件的源文件
2 // HelloWorld.pch 將作為預編譯頭
3 // stdafx.obj 將包含預編譯類型信息
4 
5 #include "stdafx.h"
6 
7 // TODO: 在 STDAFX.H 中
8 // 引用任何所需的附加頭文件,而不是在此文件中引用
 1 // HelloWorld.h
 2 #pragma once
 3 
 4 class CHelloWorld: public CWindowWnd, public INotifyUI    // 繼承自CWindowWnd和INotifyUI
 5 {
 6     //////////////////////////////////////////////////////////////////////////
 7     // 構造函數及自定義函數
 8 public:
 9     CHelloWorld();
10     void Init();    // 界面控件一些初始化、比如某個按鈕最開始是禁用狀態就應該在這個時候處理...
11     void OnOK();    // 點擊OK按鈕的處理
12     void OnClose();    // 點擊Close按鈕的處理
13 
14     // WM_CREATE消息的處理
15     LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
16     // WM_NCHITTEST消息的處理
17     LRESULT OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
18     LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
19     LRESULT OnNcActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
20     LRESULT OnGetMinMaxInfo(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
21     LRESULT OnSysCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
22     LRESULT OnNcCalcSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
23 
24     //////////////////////////////////////////////////////////////////////////
25     // 繼承自CWindowWnd類
26 public:
27     LPCTSTR GetWindowClassName() const ;    // 純虛函數,必須有實現
28     UINT GetClassStyle() const;
29     void OnFinalMessage(HWND /*hWnd*/);    // 窗口接收到最后一條消息的處理
30     LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);    // 消息響應函數
31 
32     //////////////////////////////////////////////////////////////////////////
33 
34     // 繼承自INotifyUI接口
35 public:
36     void Notify(TNotifyUI& msg);
37 
38     //////////////////////////////////////////////////////////////////////////
39 
40     // 成員變量
41     //////////////////////////////////////////////////////////////////////////
42 private:
43     CButtonUI*        m_pBtnOK;    // 按鈕控件
44     CButtonUI*        m_pBtnClose;// 按鈕控件
45 
46     CPaintManagerUI m_pm;    // 窗口繪制器
47 };
  1 // HelloWorld.cpp : 定義應用程序的入口點。
  2 //
  3 
  4 #include "stdafx.h"
  5 #include "HelloWorld.h"
  6 #include "resource.h"
  7 
  8 int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPSTR /*lpCmdLine*/, int nCmdShow)
  9 {
 10     CPaintManagerUI::SetInstance(hInstance);    // 將程序實例與皮膚繪制管理器掛鈎
 11     // 設置皮膚庫的資源路徑,資源有圖片、xml文件等
 12     CPaintManagerUI::SetResourcePath(CPaintManagerUI::GetInstancePath() + TEXT("skin"));
 13 
 14     HRESULT Hr = ::CoInitialize(NULL);
 15     if( FAILED(Hr) ) return 0;
 16 
 17     CHelloWorld* pHW = new CHelloWorld();
 18     if (pHW == NULL)
 19         return 0;
 20     pHW->Create(NULL, TEXT("Hello World"), UI_WNDSTYLE_FRAME, WS_EX_WINDOWEDGE | WS_EX_APPWINDOW);
 21     pHW->SetIcon(IDI_HW);
 22     pHW->CenterWindow();
 23     pHW->ShowWindow();
 24     CPaintManagerUI::MessageLoop();
 25 
 26     ::CoUninitialize();
 27     return 0;
 28 }
 29 
 30 CHelloWorld::CHelloWorld()
 31 : m_pBtnOK(NULL)
 32 , m_pBtnClose(NULL)
 33 {
 34 
 35 }
 36 
 37 void CHelloWorld::Init()    // 本例中此函數其實沒有做任何事情
 38 {
 39     m_pBtnOK = static_cast<CButtonUI *>(m_pm.FindControl(TEXT("OK")));
 40     if (m_pBtnOK == NULL)
 41         return;
 42     // m_pBtnOK->OnNotify += MakeDelegate(this, &CHelloWorld::OnOK);
 43     // MakeDelegate的實現感覺很強大,這樣也可以實現把OK按鈕的時間轉接到OnOK來處理
 44 
 45     m_pBtnClose = static_cast<CButtonUI *>(m_pm.FindControl(TEXT("Close")));
 46     if (m_pBtnClose == NULL)
 47         return;
 48     //m_pBtnClose->OnNotify += MakeDelegate(this, &CHelloWorld::OnClose);
 49 }
 50 
 51 void CHelloWorld::OnOK()
 52 {
 53     Close();    // CWindowWnd繼承來的函數Close,是關閉自己
 54 }
 55 
 56 void CHelloWorld::OnClose()
 57 {
 58     Close();
 59 }
 60 
 61 LPCTSTR CHelloWorld::GetWindowClassName() const
 62 {
 63     return TEXT("HelloWorld");
 64 }
 65 
 66 UINT CHelloWorld::GetClassStyle() const
 67 {
 68     return UI_CLASSSTYLE_FRAME | CS_DBLCLKS;
 69 }
 70 
 71 void CHelloWorld::OnFinalMessage( HWND /*hWnd*/ )
 72 {
 73     delete this;
 74 }
 75 
 76 LRESULT CHelloWorld::HandleMessage( UINT uMsg, WPARAM wParam, LPARAM lParam )
 77 {
 78     LRESULT lRes = 0;
 79     BOOL bHandled = TRUE;
 80     switch (uMsg)
 81     {
 82     case WM_CREATE:
 83         lRes = OnCreate(uMsg ,wParam, lParam, bHandled);
 84         break;
 85 
 86     case WM_DESTROY:
 87         ::PostQuitMessage(0);
 88         bHandled = FALSE;
 89         break;
 90 
 91     case WM_NCHITTEST:
 92         lRes = OnNcHitTest(uMsg, wParam, lParam, bHandled);
 93         break;
 94 
 95     case WM_KEYDOWN:
 96         if (wParam == VK_ESCAPE)
 97         {
 98             OnClose();
 99         }
100         break;
101 
102     case WM_SIZE:
103         lRes = OnSize(uMsg, wParam, lParam, bHandled);
104         break;
105 
106     case WM_NCACTIVATE:
107         lRes = OnNcActivate(uMsg, wParam, lParam, bHandled);
108         break;
109 
110     case WM_GETMINMAXINFO:
111         lRes = true;
112         OnGetMinMaxInfo(uMsg, wParam, lParam, bHandled);        
113         break;
114 
115     case WM_SYSCOMMAND:
116         lRes = OnSysCommand(uMsg, wParam, lParam, bHandled); 
117         break;
118 
119     case WM_NCCALCSIZE:
120         lRes = OnNcCalcSize(uMsg, wParam, lParam, bHandled); 
121         break;
122 
123     default:
124         bHandled = FALSE; break;
125     }
126     
127     if (bHandled) return lRes;
128     if (m_pm.MessageHandler(uMsg, wParam, lParam, lRes) != 0)
129         return lRes;
130     return CWindowWnd::HandleMessage(uMsg, wParam, lParam);
131 }
132 
133 LRESULT CHelloWorld::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
134 {
135     //LONG styleValue = ::GetWindowLong(*this, GWL_STYLE);
136     //styleValue &= ~WS_CAPTION;
137     //::SetWindowLong(*this, GWL_STYLE, styleValue | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
138     //RECT rcClient;
139     //::GetClientRect(*this, &rcClient);
140     //::SetWindowPos(*this, NULL, rcClient.left, rcClient.top, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top, SWP_FRAMECHANGED);
141 
142     m_pm.Init(m_hWnd);    // 把自己的窗口句柄與窗口繪制管理器掛接在一起
143     CDialogBuilder builder;
144     // 根據xml的配置來創建控件
145     CControlUI* pRoot = builder.Create(TEXT("HelloWorld.xml"), (UINT)0, NULL, &m_pm);
146     ASSERT(pRoot && "Failure to parse XML");
147     m_pm.AttachDialog(pRoot);    // 把上面的控件繪制到本窗口上,之前有把m_hWnd傳給m_pm
148     m_pm.AddNotifier(this);    // 把自己加入到CPaintManagerUI的m_aNotifiers數組中,用於處理Notify函數
149     Init();
150     return 0;
151 
152 }
153 
154 LRESULT CHelloWorld::OnSize( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
155 {
156     SIZE szRoundCorner = m_pm.GetRoundCorner();    // GetRoundCorner用來獲取xml中的Window標簽中roundcorner屬性值,該值指示圓角的長寬
157     if( !::IsIconic(*this) && (szRoundCorner.cx != 0 || szRoundCorner.cy != 0) ) {
158         CRect rcWnd;
159         ::GetWindowRect(*this, &rcWnd);
160         rcWnd.Offset(-rcWnd.left, -rcWnd.top);    // rcWnd.right就成為了窗口的寬度了
161         rcWnd.right++; rcWnd.bottom++;
162         HRGN hRgn = ::CreateRoundRectRgn(rcWnd.left, rcWnd.top, rcWnd.right, rcWnd.bottom, szRoundCorner.cx, szRoundCorner.cy);
163         ::SetWindowRgn(*this, hRgn, TRUE);    // 窗口圓角化處理
164         ::DeleteObject(hRgn);
165     }
166 
167     bHandled = FALSE;
168     return 0;
169 }
170 
171 LRESULT CHelloWorld::OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
172 {
173     POINT pt; pt.x = GET_X_LPARAM(lParam); pt.y = GET_Y_LPARAM(lParam);
174     ::ScreenToClient(*this, &pt);
175 
176     RECT rcClient;
177     ::GetClientRect(*this, &rcClient);
178 
179     if( !::IsZoomed(*this) ) {
180         RECT rcSizeBox = m_pm.GetSizeBox();    // GetSizeBox用來獲取xml中Window標簽的sizebox屬性,該屬性指示你的鼠標移動到窗口邊框多少個像素會變成指示符(這個指示符表示可以改變窗口大小的指示符)
181         if( pt.y < rcClient.top + rcSizeBox.top ) {
182             if( pt.x < rcClient.left + rcSizeBox.left ) return HTTOPLEFT;
183             if( pt.x > rcClient.right - rcSizeBox.right ) return HTTOPRIGHT;
184             return HTTOP;
185         }
186         else if( pt.y > rcClient.bottom - rcSizeBox.bottom ) {
187             if( pt.x < rcClient.left + rcSizeBox.left ) return HTBOTTOMLEFT;
188             if( pt.x > rcClient.right - rcSizeBox.right ) return HTBOTTOMRIGHT;
189             return HTBOTTOM;
190         }
191         if( pt.x < rcClient.left + rcSizeBox.left ) return HTLEFT;
192         if( pt.x > rcClient.right - rcSizeBox.right ) return HTRIGHT;
193     }
194 
195     RECT rcCaption = m_pm.GetCaptionRect();    // GetCaptionRect用來獲取xml中Window標簽的caption屬性,該屬性指示標題欄的大小
196     if( pt.x >= rcClient.left + rcCaption.left && pt.x < rcClient.right - rcCaption.right && pt.y >= rcCaption.top && pt.y < rcCaption.bottom ) {
197             CControlUI* pControl = static_cast<CControlUI*>(m_pm.FindControl(pt));
198             if( pControl && _tcsicmp(pControl->GetClass(), _T("ButtonUI")) != 0 && _tcsicmp(pControl->GetClass(), _T("OptionUI")) != 0)
199                 return HTCAPTION;
200     }
201 
202     return HTCLIENT;
203 }
204 
205 void CHelloWorld::Notify( TNotifyUI& msg )
206 {
207     if (msg.sType == TEXT("click"))    // click事件
208     {
209         if (msg.pSender->GetName() == TEXT("OK"))
210             OnOK();
211         if (msg.pSender->GetName() == TEXT("Close"))
212             OnClose();
213     }
214     else if (msg.sType == TEXT("windowinit"))
215     {
216     }
217 }
218 
219 LRESULT CHelloWorld::OnNcActivate( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
220 {
221     if( ::IsIconic(*this) ) bHandled = FALSE;
222     return (wParam == 0) ? TRUE : FALSE;
223 }
224 
225 LRESULT CHelloWorld::OnGetMinMaxInfo( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
226 {
227     MONITORINFO oMonitor = {};
228     oMonitor.cbSize = sizeof(oMonitor);
229     ::GetMonitorInfo(::MonitorFromWindow(*this, MONITOR_DEFAULTTOPRIMARY), &oMonitor);
230     CRect rcWork = oMonitor.rcWork;
231     rcWork.Offset(-rcWork.left, -rcWork.top);
232 
233     LPMINMAXINFO lpMMI = (LPMINMAXINFO) lParam;
234     lpMMI->ptMaxPosition.x    = rcWork.left;
235     lpMMI->ptMaxPosition.y    = rcWork.top;
236     lpMMI->ptMaxSize.x        = rcWork.right;
237     lpMMI->ptMaxSize.y        = rcWork.bottom;
238 
239     bHandled = FALSE;
240     return 0;
241 }
242 
243 LRESULT CHelloWorld::OnSysCommand( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
244 {
245     if (wParam == SC_CLOSE)
246     {
247         bHandled = TRUE;
248         SendMessage(WM_CLOSE);
249         return 0;
250     }
251 #if defined(WIN32) && !defined(UNDER_CE)
252     BOOL bZoomed = ::IsZoomed(*this);
253     LRESULT lRes = CWindowWnd::HandleMessage(uMsg, wParam, lParam);
254     if( ::IsZoomed(*this) != bZoomed )
255     {
256     }
257 #else
258     LRESULT lRes = CWindowWnd::HandleMessage(uMsg, wParam, lParam);
259 #endif
260     return lRes;
261 }
262 
263 LRESULT CHelloWorld::OnNcCalcSize( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
264 {
265     return 0;
266     // wParam為TRUE時,返回0將會使窗口的大小變為客戶區的大小,也就是說這將把窗口的標題欄、窗口邊框移除,只顯示客戶區
267 }
 1 // xml皮膚配置文件
 2 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 3 <Window size="400,250" caption="0,0,0,30" roundcorner="6,6" sizebox="4,4,4,4" mininfo="100,50" maxinfo="500,300">
 4     <VerticalLayout  bkcolor="#FF000000">
 5         <HorizontalLayout width="400" height="30" bkimage="file=&apos;top_bg.png&apos; corner=&apos;5,5,5,5&apos;">
 6             <HorizontalLayout widht="80">
 7                 <Button name="OK" text="OK" align="center" width="80" height="30" textcolor="#FFC8C8C8" disabletextcolor="#FFA7A6AA" normalimage="file=&apos;BtnOK.png&apos; source=&apos;0,0,80,30&apos;" hotimage="file=&apos;BtnOK.png&apos; source=&apos;80,0,160,30&apos;" pushedimage="file=&apos;BtnOK.png&apos; source=&apos;160,0,240,30&apos;" disabledimage="file=&apos;BtnOK.png&apos; source=&apos;240,0,320,30&apos;" />
 8             </HorizontalLayout>
 9             <HorizontalLayout width="240">
10                 <Label name="caption" text="Hello World" textcolor="#FFFFFFFF" align="center" />
11             </HorizontalLayout>
12             <HorizontalLayout widht="80">
13                 <Button name="Close" text="Close" align="center" width="79" height="30" textcolor="#FFC8C8C8" disabletextcolor="#FFA7A6AA" normalimage="file=&apos;BtnClose.png&apos; source=&apos;0,0,79,30&apos;" hotimage="file=&apos;BtnClose.png&apos; source=&apos;80,0,158,30&apos;" pushedimage="file=&apos;BtnClose.png&apos; source=&apos;159,0,237,30&apos;" disabledimage="file=&apos;BtnClose.png&apos; source=&apos;238,0,316,30&apos;" />
14             </HorizontalLayout>
15         </HorizontalLayout>
16         <VerticalLayout bkimage="file=&apos;MBbottombg.png&apos; corner=&apos;6,6,6,6&apos;">
17             
18         </VerticalLayout>
19     </VerticalLayout>
20 </Window>


其他:

1.開始寫完程序運行后發現任務欄上沒有圖標,原來可以用SetIcon函數來設置,SetIcon函數的參數是一個資源ID(UINT類型),可以自己繪制一個圖標或者導入一個,然后將該圖標的id傳入即可,還是比較方便的。注意的是SetIcon不需要使用MAKEINTRESOURCE來轉換,在SetIcon函數內調用了MAKEINTRESOURCE。

2.在用窗口類的Create函數時,指定UI_WNDSTYLE_FRAME為第三個參數時,窗口可以雙擊最大化,而使用UI_WNDSTYLE_DIALOG時無法最大化。原來

1 #define UI_WNDSTYLE_FRAME      (WS_VISIBLE | WS_OVERLAPPEDWINDOW)
2 #define UI_WNDSTYLE_CHILD      (WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN)
3 #define UI_WNDSTYLE_DIALOG     (WS_VISIBLE | WS_POPUPWINDOW | WS_CAPTION | WS_DLGFRAME | WS_CLIPSIBLINGS | WS_CLIPCHILDREN)

WS_OVERLAPPEDWINDOW默認帶有WM_MAXIMIZEBOX屬性,固默認可以雙擊最大化。WS_POPUPWINDOW默認有WS_BORDER,WS_POPUP和WS_SYSMENU屬性,沒有WM_MAXIMIZEBOX屬性,固POPUPWINDOW默認無法雙擊最大化。

3.WM_NCCALCSIZE消息的處理,MSDN中有這么一段描述

When wParam is TRUE, simply returning 0 without processing the NCCALCSIZE_PARAMS rectangles will cause the client area to resize to the size of the window, including the window frame. This will remove the window frame and caption items from your window, leaving only the client area displayed.

也就是說這個消息處理時返回0,則窗口將會沒有標題欄和外邊框,只有客戶區了。

4.WM_NCHITTEST消息的處理,可以返回HTTOPLEFT(窗口的左上角,鼠標變為可調邊框標識)、HTTOPRIGHT等。返回HTCAPTION標識擊中為標題欄,返回HTCLIENT標識擊中為客戶區。

5.按鍵消息的處理:可繼承IMessageFilterUI,該接口有MessageHandler純虛函數,自己要實現對按鍵的處理;在OnCreate中把自己加入到繪制管理器對象的m_aPreMessageFilters預處理消息數組中。這樣在繪制管理器的MessageLoop()中將調用TranslateMessage按鍵處理,在TranslateMessage又將調用PreMessageHandler,然后PreMessageHandler中又將調用MessageHandler函數(即那個需要處理按鍵消息的窗口類的函數)

6.foreimage可以在按鈕的背景上加入前景圖片;控件的float設為true時,改變窗口大小,控件的顯示會有問題,只能顯示控件的一部分,解決辦法是使用布局來控制控件位置,不用設置控件位置;relativePos要與float="true"同用,可調節百分比;pos屬性也要與float="true"同用才可調節控件位置;皮膚科刷新有問題,必須依賴於背景顏色;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM