日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

Win32 SDK 编写截图小工具

發(fā)布時(shí)間:2025/3/13 编程问答 14 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Win32 SDK 编写截图小工具 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

開發(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í)有灰暗的效果


ATOM MyRegisterClass(PWNDCLASSEX wcex,HINSTANCE hInstance) {...wcex->hCursor = LoadCursor(NULL, IDC_CROSS);wcex->hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);...return RegisterClassEx(wcex); }

(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è)開始截圖的命令消息

注意窗口銷毀時(shí)注銷熱鍵,在WM_DESTROY中

UnregisterHotKey(hWnd, 1346);UnregisterHotKey(hWnd, 1347);

(4)在不進(jìn)行截圖時(shí),將窗口最小化到托盤,這里要用到 API函數(shù)Shell_NotifyIcon和結(jié)構(gòu)體NOTIFYICONDATA,先來(lái)看下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)的長(zhǎng)度,用“位”來(lái)做單位。一般在程序中,我們用(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來(lái)得到句柄。例如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所代表的窗口。所以說(shuō),在uFlags中,一般都得標(biāo)志它有效。這里一般都是自定義的消息。

szTip : 鼠標(biāo)移動(dòng)到托盤圖標(biāo)上時(shí)的提示文字。

我們這里用一個(gè)自定義消息來(lái)接收托盤圖標(biāo)的消息:

#define MY_ICON_MESSAGE (WM_USER+1) ... NOTIFYICONDATA g_nid; ... g_nid.uCallbackMessage = MY_ICON_MESSAGE;
那么此時(shí),第三個(gè)參數(shù)可以隨便填。接下來(lái)處理這個(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)接下去來(lái)處理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)的操作來(lái)對(duì)這張全屏圖“剪裁”)hSrcDC是一個(gè)窗口消息處理函數(shù)的靜態(tài)局部DC句柄。

接著利用API函數(shù)SetLayeredWindowAttributes來(lái)設(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 0x00000002
g_State 是一個(gè)全局變量,用以記錄是否在截圖狀態(tài),在鼠標(biāo)的消息處理函數(shù)中會(huì)對(duì)此變量進(jìn)行判斷,是的話再進(jìn)行相應(yīng)的操作。


(6)接下去跟蹤鼠標(biāo)的行為“剪裁”剛才的桌面DC,先找到需要的矩形塊坐標(biāo)。

主要過(guò)程為:

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)容,并保存位圖文件。最后使窗口隱藏起來(lá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 编写截图小工具的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。