Win32 SDK 编写截图小工具
開發(fā)環(huán)境為windows xp,vc6
主要方案為,創(chuàng)建一個(gè)主窗口,不進(jìn)行截圖的時(shí)候?qū)⑵潆[藏,并在托盤區(qū)創(chuàng)建小圖標(biāo),截圖時(shí)使窗口全屏透明,捕捉鼠標(biāo)行為截圖保存,再使窗口隱藏。
以下根據(jù)主要步驟將核心內(nèi)容點(diǎn)出:
(1)注冊(cè)窗口類時(shí),將背景色定為黑色,以使截圖時(shí)有灰暗的效果
(2)創(chuàng)建窗口時(shí),用到兩個(gè)擴(kuò)展風(fēng)格,WS_EX_LAYERED,WS_EX_TOOLWINDOW
前者是將窗口透明化必須設(shè)置的窗口風(fēng)格,后者使窗口成為一個(gè)工具窗口,不顯示在任務(wù)欄中。
HWND hWnd = CreateWindowEx(WS_EX_LAYERED | WS_EX_TOOLWINDOW, "MYSCREENSHOT", 0, WS_POPUP,CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);(3)注冊(cè)兩套熱鍵,用RegisterHotKey
函數(shù)原型為:
BOOL RegisterHotKey(HWND hWnd, // handle to windowint id, // hot key identifierUINT fsModifiers, // key-modifier optionsUINT vk // virtual-key code );RegisterHotKey(hWnd, 1346, MOD_ALT | MOD_CONTROL, 65);RegisterHotKey(hWnd, 1347, MOD_CONTROL, 222);65為A的虛鍵碼,222為' or " 的虛鍵碼,適用于左手與右手。
這樣當(dāng)按下這兩個(gè)組合鍵時(shí),窗口會(huì)受到一個(gè)??? WM_HOTKEY??? 消息,其中,lParam的低位字顯示了alt或是control鍵是否被按下,高位字為虛鍵碼,那么我們只需要在窗口函數(shù)中處理該消息,發(fā)送一個(gè)命令消息開始截圖:
case WM_HOTKEY:{if(HIWORD(lParam) == 65 || HIWORD(lParam) == 222)SendMessage(hWnd, WM_COMMAND, MAKEWPARAM(IDM_RUN, 0), 0);}break;IDM_RUN 是一個(gè)開始截圖的命令消息
(4)在不進(jìn)行截圖時(shí),將窗口最小化到托盤,這里要用到 API函數(shù)Shell_NotifyIcon和結(jié)構(gòu)體NOTIFYICONDATA,先來看下NOTIFYICONDATA:
typedef struct _NOTIFYICONDATA { DWORD cbSize; HWND hWnd; UINT uID; UINT uFlags; UINT uCallbackMessage; HICON hIcon; char szTip[64]; } NOTIFYICONDATA, *PNOTIFYICONDATA; 其中,cbSize : 結(jié)構(gòu)的長度,用“位”來做單位。一般在程序中,我們用(DWORD)sizeof(NOTIFYICONDATA) 給它賦值。
HWnd : 一個(gè)句柄,如果對(duì)托盤中的圖標(biāo)進(jìn)行操作,相應(yīng)的消息就傳給這個(gè)句柄所代表的窗口。自然了,大多數(shù)情況下是this->m_hWnd嘍。
uID : 在工程中定義的圖標(biāo)ID?
uFlags : 這個(gè)成員標(biāo)志著其他哪些成員的數(shù)據(jù)是有效的,分別為NIF_ICON, NIF_MESSAGE, NIF_TIP,分別代表著數(shù)據(jù)有效的成員是hIcon, uCallbackMessage, szTip。當(dāng)然,三個(gè)值可以用“|”聯(lián)系到一起。下面分別對(duì)涉及到的成員進(jìn)行闡述?
hIcon : 要增加,刪除或修改的圖標(biāo)句柄。如果只知道個(gè)uID, 一般可能會(huì)用函數(shù)LoadIcon來得到句柄。例如LoadIcon ( AfxGetInstanceHandle() ,MAKEINTRESOURCE (IDR_MAINFRAME) )。
uCallbackMessage : 這在對(duì)托盤區(qū)的操作中,是比較重要的數(shù)據(jù)成員。這是個(gè)消息標(biāo)志,當(dāng)用鼠標(biāo)對(duì)托盤區(qū)相應(yīng)圖標(biāo)進(jìn)行操作的時(shí)候,就會(huì)傳遞消息給Hwnd所代表的窗口。所以說,在uFlags中,一般都得標(biāo)志它有效。這里一般都是自定義的消息。
szTip : 鼠標(biāo)移動(dòng)到托盤圖標(biāo)上時(shí)的提示文字。
我們這里用一個(gè)自定義消息來接收托盤圖標(biāo)的消息:
#define MY_ICON_MESSAGE (WM_USER+1) ... NOTIFYICONDATA g_nid; ... g_nid.uCallbackMessage = MY_ICON_MESSAGE;那么此時(shí),第三個(gè)參數(shù)可以隨便填。接下來處理這個(gè)消息,其中,wParam接收的是圖標(biāo)的ID,而lParam接收的是鼠標(biāo)的行為 case MY_ICON_MESSAGE:{switch(lParam){case WM_RBUTTONDOWN:{HMENU hMenu = CreateMenu();HMENU hPopupMenu = CreateMenu();AppendMenu(hMenu, MF_POPUP, (UINT_PTR)hPopupMenu, 0);AppendMenu(hPopupMenu, MF_STRING, IDM_RUN, "&Run");AppendMenu(hPopupMenu, MF_SEPARATOR, 0, 0);AppendMenu(hPopupMenu, MF_STRING, IDM_QUIT, "&Quit");POINT point;GetCursorPos(&point);SetForegroundWindow(hWnd);TrackPopupMenu(hPopupMenu, TPM_LEFTALIGN, point.x, point.y, 0, hWnd, 0);}break;case WM_LBUTTONDBLCLK:SendMessage(hWnd, WM_COMMAND, MAKEWPARAM(IDM_RUN, 0), 0);break;}}break;
右鍵單擊時(shí),彈出一個(gè)菜單,有兩個(gè)選項(xiàng),運(yùn)行和退出,當(dāng)左鍵雙擊時(shí),與運(yùn)行截圖有相同的作用,發(fā)送一個(gè)IDM_RUN 的命令消息。注意,TrackPopupMenu之前的SetForegroundWindow是必要的,沒有這一句,則彈出的菜單不會(huì)自動(dòng)消失。
(5)接下去來處理IDM_RUN消息:
case IDM_RUN:{g_nid.hIcon = LoadIcon(g_hInstance, (LPCTSTR)IDI_ON); Shell_NotifyIcon(NIM_MODIFY, &g_nid);hSrcDC = GetDC(GetDesktopWindow());HMODULE hModule = LoadLibrary("User32.dll");lpfnSetLayeredWindowAttributes myfunc = (lpfnSetLayeredWindowAttributes)GetProcAddress(hModule, "SetLayeredWindowAttributes"); FreeLibrary(hModule);ShowWindow(hWnd, SW_MAXIMIZE);myfunc(hWnd, 0, 100, LWA_ALPHA);g_State = TRUE;}break;首先是一個(gè)替換托盤區(qū)圖標(biāo)的操作,顯示截圖正在進(jìn)行中。
然后先取得桌面DC,(先把全屏給截了,然后再跟蹤鼠標(biāo)的操作來對(duì)這張全屏圖“剪裁”)hSrcDC是一個(gè)窗口消息處理函數(shù)的靜態(tài)局部DC句柄。
接著利用API函數(shù)SetLayeredWindowAttributes來設(shè)置窗口為透明,其函數(shù)原型為:
BOOL SetLayeredWindowAttributes(HWND hwnd, // handle to the layered windowCOLORREF crKey, // specifies the color keyBYTE bAlpha, // value for the blend functionDWORD dwFlags // action );詳細(xì)的解答請(qǐng)參照MSDN
這里需要申明對(duì)該函數(shù)的指針,注意,LWA_ALPHA需要自行定義
typedef BOOL (WINAPI *lpfnSetLayeredWindowAttributes)(HWND,COLORREF,BYTE,DWORD); ... #define LWA_ALPHA 0x00000002g_State 是一個(gè)全局變量,用以記錄是否在截圖狀態(tài),在鼠標(biāo)的消息處理函數(shù)中會(huì)對(duì)此變量進(jìn)行判斷,是的話再進(jìn)行相應(yīng)的操作。
(6)接下去跟蹤鼠標(biāo)的行為“剪裁”剛才的桌面DC,先找到需要的矩形塊坐標(biāo)。
主要過程為:
1.在WM_LBUTTONDOWN中記錄第一個(gè)點(diǎn),將它保存在靜態(tài)POINT變量中;
2.在WM_MOUSEMOVE中在透明窗口上實(shí)時(shí)刷新并畫線以顯示截圖的區(qū)域;
3.在WM_LBUTTONUP中記錄第二個(gè)點(diǎn),從而取得需要剪裁的區(qū)域矩形,用BitBlt復(fù)制DC內(nèi)容,并保存位圖文件。最后使窗口隱藏起來,更換托盤區(qū)圖標(biāo)等初始化工作。
具體代碼在此不再羅嗦了,詳見源碼。
成品exe及源代碼:點(diǎn)擊打開鏈接
轉(zhuǎn)載于:https://www.cnblogs.com/silyvin/archive/2012/05/07/9106906.html
與50位技術(shù)專家面對(duì)面20年技術(shù)見證,附贈(zèng)技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的Win32 SDK 编写截图小工具的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SQL反模式笔记7——多列属性
- 下一篇: 语法分析生成器 - LEX