對於不習慣用MFC的程序員來說,寫界面應該是一個頭疼的事情了。調用duilib等開源界面庫的不討論,本文主要說說Windows的原生界面功能開發,作為一篇總結,幫助新手入門。
1、窗口
主要通過新建資源窗口實現布局,調用就通過 DialogBox 和 CreateDialog 實現界面的顯示。其中 DialogBox 為模態窗口, CreateDialog 為非模態窗口,簡要說說區別:
模態窗口:在沒有父窗口的時候,調用 DialogBox 實現顯示窗口。系統在 DialogBox 這兒卡住,直到窗口關閉後繼續以下的代碼。
非模態窗口:調用 CreateDialog 之後,代碼繼續往下執行。如果沒有父窗口,則執行 GetMessage TranslateMessage DispatchMessage 這幾個代碼,如果存在父窗口,則只需要進入父窗口的消息循環,子窗口也可以進行消息循環響應。
2、控件
Windows 下面的控件種類繁多,在此我簡要介紹幾種的使用
2.1、托盤圖標
// // 文件:notifyicon.h // 類:hNotifyIcon // 主要功能:實現系統托盤圖標設置 // #pragma once #includeclass hNotifyIcon { NOTIFYICONDATA h_nid; public: hNotifyIcon (HWND hWnd, HICON hIcon, LPCTSTR lpTitle, LPCTSTR lpTips = NULL, int iTimeOut = 5); ~hNotifyIcon (); BOOL Show (); BOOL Hide (); BOOL Message (LPCTSTR lpMsg, UINT niif_InfoWarningError); BOOL IsShow (); };
// // 文件:notifyicon.cpp // 類:hNotifyIcon // 主要功能:實現系統托盤圖標設置 // #include "notifyicon.h" #pragma comment(lib, "Shell32.lib") hNotifyIcon::hNotifyIcon (HWND hWnd, HICON hIcon, LPCTSTR lpTitle, LPCTSTR lpTips, int iTimeOut) { this->h_nid.cbSize = sizeof(NOTIFYICONDATA); this->h_nid.hWnd = hWnd; this->h_nid.uID = GetTickCount ()&0xFFFF; this->h_nid.dwState = this->h_nid.dwStateMask = 0; this->h_nid.uCallbackMessage = WM_USER+1; this->h_nid.hBalloonIcon = this->h_nid.hIcon = hIcon; if (lpTips) lstrcpy ((LPTSTR)this->h_nid.szTip, lpTips); else lstrcpy ((LPTSTR)this->h_nid.szTip, lpTitle); lstrcpy ((LPTSTR)this->h_nid.szInfoTitle, lpTitle); this->h_nid.uTimeout = iTimeOut; } hNotifyIcon::~hNotifyIcon () { if (this->IsShow ()) this->Hide (); } BOOL hNotifyIcon::Show () { this->h_nid.uFlags = NIF_ICON|NIF_INFO|NIF_MESSAGE; BOOL bRet = (BOOL) Shell_NotifyIcon (NIM_ADD, &this->h_nid); this->h_nid.uFlags = NIF_INFO; this->h_nid.dwInfoFlags = NIIF_INFO; return bRet; } BOOL hNotifyIcon::Hide () { this->h_nid.uFlags = NULL; return (BOOL) Shell_NotifyIcon (NIM_DELETE, &this->h_nid); } BOOL hNotifyIcon::Message (LPCTSTR lpMsg, UINT niif_InfoWarningError) { this->h_nid.dwInfoFlags = niif_InfoWarningError; lstrcpy (this->h_nid.szInfo, lpMsg); return (BOOL) Shell_NotifyIcon (NIM_MODIFY, &this->h_nid); } BOOL hNotifyIcon::IsShow () { return (BOOL)this->h_nid.uFlags; }
實現上很簡單,和MFC類似,對顯示、隱藏、發送泡泡通知等功能進行了封裝,需要使用時直接new一個對象出來,簡單調用幾下就完了。
2.2、ListView / ListCtrl
//風格 DWORD dwStyle = ListView_GetExtendedListViewStyle(hList); dwStyle |= LVS_EX_FULLROWSELECT;//選中整行 dwStyle |= LVS_EX_CHECKBOXES;//復選框 ListView_SetExtendedListViewStyle(hList, dwStyle); //添加標頭 LV_COLUMN lc; lc.mask = LVCF_TEXT | LVCF_WIDTH; lc.cchTextMax = MAX_PATH; lc.cx = 100; lc.pszText = TEXT("列1"); ListView_InsertColumn(hList, 0, &lc); lc.cx = 100; lc.pszText = TEXT("列2"); ListView_InsertColumn(hList, 1, &lc); …… //添加行 LVITEM li; li.mask = LVIF_TEXT; li.cchTextMax = MAX_PATH; li.iSubItem = 0; li.iItem = 0;//插入第幾行,從0開始 li.pszText = TEXT("列1"); ListView_InsertItem(hList, &li); ListView_SetItemText(hList, li.iItem, 1, TEXT("列2")); …… li.iItem = 1; li.pszText = TEXT("列1"); ListView_InsertItem(hList, &li); ListView_SetItemText(hList, li.iItem, 1, TEXT("列2")); …… ……ListView / ListCtrl 的使用就方便多了,一大批 ListView_ 開頭的函數,任君選擇。
2.3、TabCtrl,也就是所謂的分頁控件
分兩步,第一步是初始化
#include第二步,處理WM_NOTIFY消息hwndTab = GetDlgItem(); hwndChild[0] = CreateDialog(); hwndChild[1] = CreateDialog(); TCITEM ti = { 0 }; ti.mask = TCIF_TEXT; ti.cchTextMax = MAX_PATH; ti.pszText = TEXT("tab1"); TabCtrl_InsertItem(hwndTab, 0, &ti); ti.pszText = TEXT("tab2"); TabCtrl_InsertItem(hwndTab, 1, &ti);
case WM_NOTIFY: if (((LOWORD(wParam)) == IDC_TAB_MAIN) && (((LPNMHDR)lParam)->code == TCN_SELCHANGE)) { for(int i=0; i簡單方便。 2.4、任務欄進度條
這個的實現比較麻煩,我放在雲盤,需要的點此下載 有兩個壓縮包,組件可以直接拿來用,源碼可以看看實現方法。另外,XP和Vista就不要試了,系統都沒有這個接口的。 2.5、其他Windows常用控件
寫一行代碼:
#include然後點進去,其他該有的都有了,比如RadioButton、CheckBox等等。並不代表所有的都有,SDK界面開發等待著你的發掘。
3、C++/SDK 調用 Gdiplus
有了標准控件,總不能沒有繪圖吧?GDI太渣,又麻煩又復雜又不支持png還有鋸齒。我在這兒簡要說說如何引用Gdiplus。
首先,頭文件和庫別少,命名空間可以不引用,看個人愛好
#include然後,下面代碼霸氣甩進WinMain開頭#pragma comment(lib, "gdiplus.lib") using namespace Gdiplus;
ULONG_PTR gdiplusToken; GdiplusStartupInput gdiplusStartupInput; GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);最後,下面代碼霸氣甩進WinMain返回前
GdiplusShutdown(gdiplusToken);介紹的差不多了。 Win32 博大精深,如有遺漏之處歡迎指正。