中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當前位置: 首頁 > news >正文

人民日報網(wǎng)站誰做的抖音seo排名系統(tǒng)哪個好用

人民日報網(wǎng)站誰做的,抖音seo排名系統(tǒng)哪個好用,四川省工程造價總站官網(wǎng),鲅魚圈網(wǎng)站在哪做目錄 前言 1 遍歷窗口句柄列表 2 使用 SendMessageTimeout 發(fā)送延時消息 3 并行發(fā)送消息實現(xiàn)模擬廣播消息 4 修改 UIPI 消息過濾器設置 5 托盤圖標刷新的處理 6 完整代碼和測試 本文屬于原創(chuàng)文章,轉(zhuǎn)載請注明出處: https://blog.csdn.net/qq_5907…

目錄

前言

1 遍歷窗口句柄列表

2 使用 SendMessageTimeout 發(fā)送延時消息

3 并行發(fā)送消息實現(xiàn)模擬廣播消息

4 修改?UIPI 消息過濾器設置

5 托盤圖標刷新的處理

6 完整代碼和測試


本文屬于原創(chuàng)文章,轉(zhuǎn)載請注明出處:

https://blog.csdn.net/qq_59075481/article/details/136175227。

前言

在 Windows 上使得設置的更改立即生效的方法不唯一。本文分析全局發(fā)送?WM_SETTINGCHANGE 消息來通知系統(tǒng)設置發(fā)生更改這一方法。該方法適用范圍比較廣泛,但有時候還是需要結(jié)合 SHChangeNotify 等函數(shù)來刷新更改,甚至還有一部分設置更改就只能重啟計算機生效。

我們知道如果使用 HWND_BROADCAST 廣播消息的話,雖然會通知所有頂級窗口,只消息窗口等窗口,但是該消息的處理在任意一個窗口處理后就會立即終止并返回,消息接收方有權(quán)不處理消息,我們并不容易獲取消息處理的詳細情況,并且他不能針對子窗口等窗口。

所以我們肯定要自己去實現(xiàn)自己的廣播消息的方式。

1 遍歷窗口句柄列表

我們首先通過 EnumWindows 和 EnumChildWindows 以遞歸的方式遍歷,獲取所有窗口句柄列表。

// Callback function for window enumeration
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{// Cast the lParam to a vector of HWND pointersstd::vector<HWND>* windowList = reinterpret_cast<std::vector<HWND>*>(lParam);// Add the window handle to the vectorwindowList->push_back(hwnd);// Enumerate child windowsEnumChildWindows(hwnd, EnumWindowsProc, lParam);// Continue enumerationreturn TRUE;
}// Enumerate all windows
std::vector<HWND> windowList;
EnumWindows(EnumWindowsProc, reinterpret_cast<LPARAM>(&windowList));

2 使用 SendMessageTimeout 發(fā)送延時消息

SendMessageTimeout 的好處是它可以比 SendMessage 多出來等待時間這個限制,SendMessage 會阻滯調(diào)用線程直到接收消息的線程處理完消息,所以不能用 SendMessage 同時發(fā)送消息到多個窗口;它比 PostMessage 也有優(yōu)勢,PostMessage 立即返回,所以在不關心處理結(jié)果的情況下我們可能選擇 PostMessage。

SendMessageTimeout 函數(shù)的聲明如下:

LRESULT SendMessageTimeoutW(HWND       hWnd,UINT       Msg,WPARAM     wParam,LPARAM     lParam,UINT       fuFlags,UINT       uTimeout,PDWORD_PTR lpdwResult
);

我們使用該函數(shù)就可以實現(xiàn)發(fā)送消息并等待一定時間,MSDN 說明如下:

https://learn.microsoft.com/zh-cn/windows/win32/api/winuser/nf-winuser-sendmessagetimeouta。

3 并行發(fā)送消息實現(xiàn)模擬廣播消息

單線程似乎并不能滿足我們同時請求多個窗口的需求。所以,我們可以將處理放置在多線程任務中。并將消息處理的結(jié)果使用鏈表來管理。

數(shù)據(jù)結(jié)構(gòu):

typedef struct __STMO_MSGEVENT {SIZE_T      nCount;SIZE_T      nSize;HWND        hWnd;BOOL        isActive;LRESULT     lResult;DWORD_PTR   lpStatus;struct __STMO_MSGEVENT* pNext[1];
} STMO_MSGEVENT, * LPSTMO_MSGEVENT;

其中,isActive 表示接收消息的線程是否在規(guī)定時間處理了消息,nSize 表示結(jié)點總數(shù),頭結(jié)點的nCount 表示所有窗口個數(shù)。?

線程執(zhí)行函數(shù):

// Function to send message to a window using SendMessageTimeout
void SendMessageToWindow(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LPSTMO_MSGEVENT* lpstmoMsg)
{// Set the timeout value (in milliseconds)DWORD timeout = 5000;// Call ChangeWindowsMessageFilterEx to modify the message filterChangeWindowMessageFilterEx(hwnd, uMsg, MSGFLT_ALLOW, 0);// Send the message using SendMessageTimeoutDWORD_PTR lpStatus = 0;LRESULT   lResult = 0;lResult = SendMessageTimeoutW(hwnd, uMsg, wParam, lParam, SMTO_ABORTIFHUNG, timeout, &lpStatus);bool oldCount = lResult > 0 ? true : false;AddNode(lpstmoMsg, hwnd, oldCount, lResult, lpStatus);}

4 修改?UIPI 消息過濾器設置

從 Vista 引入的消息安全機制將限制低完整級別程序向高完整級別程序發(fā)送消息的過程,此時可以使用 ChangeWindowMessageFilterEx 來允許特定的消息通過 UIPI。

// Call ChangeWindowsMessageFilterEx to modify the message filter
ChangeWindowMessageFilterEx(hwnd, uMsg, MSGFLT_ALLOW, 0);

指定 MSGFLT_ALLOW 以允許消息通過 UIPI。

5 托盤圖標刷新的處理

托盤圖標刷新需要單獨模擬發(fā)送 TaskbarCreated 消息。在任務欄重建時,會向系統(tǒng)中所有窗口廣播?TaskbarCreated 消息,在負責通知欄圖標的線程接收到消息時,接收消息的線程按照規(guī)范應該調(diào)用 Shell_NotifyIcon 重新創(chuàng)建通知欄圖標。

TaskbarCreated 字符串消息是通過?RegisterWindowMessage 在系統(tǒng)級別注冊的,因為該函數(shù)內(nèi)部封裝了?NtUserRegisterWindowMessage 的調(diào)用,這是一個用戶態(tài)/內(nèi)核態(tài)切換過程。通過逆向分析,我們了解到?RegisterWindowMessage 的返回值是 Global ATOM 數(shù)值的一部分,系統(tǒng)內(nèi)核在全局維護一個原子表 RTL_ATOM_TABLE 來通過哈希桶管理一些窗口進程交互需要的信息。

所以,在系統(tǒng)重啟前,TaskbarCreated 消息對應的 IntAtom 索引號保持不變,該值與 explorer 的重啟無關。

調(diào)用 RegisterWindowMessage 并指定?"TaskbarCreated" 字符串將首先檢索消息是否已經(jīng)在 ATOM 表中注冊。由于該消息在系統(tǒng)初始化時已經(jīng)注冊,所以,執(zhí)行過程只會增加該消息的引用計數(shù)而不會重建消息。

所以,我們可以利用 RegisterWindowMessage 作為一個官方支持的技巧,輕松獲取"TaskbarCreated"消息的窗口消息碼,調(diào)用在非消息線程/非窗口進程/非系統(tǒng)進程就可以調(diào)用成功。所以該消息不會失敗,除非交互系統(tǒng)未能夠完成初始化。

// 該字符串消息使用系統(tǒng)原子表,返回值是 IntAtom 編號,
// 一般情況下在計算機重啟時才刷新。
UINT QueryTaskbarCreateMsg()
{return RegisterWindowMessageW(L"TaskbarCreated");
}

6 完整代碼和測試

#include <Windows.h>
#include <iostream>
#include <vector>
#include <thread>#pragma comment(lib, "User32.lib")typedef struct __STMO_MSGEVENT {SIZE_T      nCount;HWND        hWnd;BOOL        isActive;LRESULT     lResult;DWORD_PTR   lpStatus;struct __STMO_MSGEVENT* pNext[1];
} STMO_MSGEVENT, * LPSTMO_MSGEVENT;LPSTMO_MSGEVENT CreateNode(HWND hWnd) {LPSTMO_MSGEVENT newNode = (LPSTMO_MSGEVENT)malloc(sizeof(STMO_MSGEVENT));newNode->nCount = 0;newNode->hWnd = hWnd;newNode->isActive = FALSE;newNode->lResult = 0;newNode->lpStatus = 0;return newNode;
}void AddNode(LPSTMO_MSGEVENT* pList, HWND hWnd, LRESULT lResult, DWORD_PTR lpStatus) {LPSTMO_MSGEVENT newNode = CreateNode(hWnd);newNode->isActive = (lResult > 0);newNode->lResult = lResult;newNode->lpStatus = lpStatus;newNode->pNext[0] = *pList;*pList = newNode;(*pList)->nCount++;
}void SendMessageToWindow(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LPSTMO_MSGEVENT* lpstmoMsg)
{DWORD timeout = 5000;ChangeWindowMessageFilterEx(hwnd, uMsg, MSGFLT_ALLOW, 0);DWORD_PTR lpStatus = 0;LRESULT lResult = SendMessageTimeoutW(hwnd, uMsg, wParam, lParam, SMTO_ABORTIFHUNG, timeout, &lpStatus);//LPSTMO_MSGEVENT newNode = CreateNode(hwnd);//newNode->isActive = (lResult > 0);// newNode->lResult = lResult;//newNode->lpStatus = lpStatus;AddNode(lpstmoMsg, hwnd, lResult, lpStatus);
}BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{std::vector<HWND>* windowList = reinterpret_cast<std::vector<HWND>*>(lParam);windowList->push_back(hwnd);EnumChildWindows(hwnd, EnumWindowsProc, lParam);return TRUE;
}void TraverseList(LPSTMO_MSGEVENT pList) {LPSTMO_MSGEVENT pNode = pList;while (pNode != nullptr) {std::cout << "hWnd: " << pNode->hWnd << std::endl;std::cout << "isActive: " << (pNode->isActive ? "true" : "false") << std::endl;std::cout << "lResult: " << pNode->lResult << "  lpStatus: " << pNode->lpStatus << std::endl;pNode = pNode->pNext[0];}
}void FreeList(LPSTMO_MSGEVENT* pList) {LPSTMO_MSGEVENT pNode = *pList;while (pNode != nullptr) {LPSTMO_MSGEVENT temp = pNode;pNode = pNode->pNext[0];free(temp);}*pList = nullptr;
}// 該字符串消息使用系統(tǒng)原子表,返回值是 IntAtom 編號,
// 一般情況下在計算機重啟時才刷新。
UINT QueryTaskbarCreateMsg()
{return RegisterWindowMessageW(L"TaskbarCreated");
}int main()
{std::vector<HWND> windowList;EnumWindows(EnumWindowsProc, reinterpret_cast<LPARAM>(&windowList));SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, SPI_SETNONCLIENTMETRICS, 0);std::vector<std::thread> threads;UINT uMsg = WM_SETTINGCHANGE;WPARAM wParam = SPI_SETNONCLIENTMETRICS;LPARAM lParam = (LPARAM)0;LPSTMO_MSGEVENT msgev = nullptr;for (HWND hwnd : windowList){threads.emplace_back(SendMessageToWindow, hwnd, uMsg, wParam, lParam, &msgev);}for (std::thread& thread : threads){thread.join();}std::cout << "List contents:\n";TraverseList(msgev);FreeList(&msgev);return 0;
}

?

#include <Windows.h>
#include <iostream>
#include <vector>
#include <thread>typedef struct __STMO_MSGEVENT {SIZE_T      nCount;SIZE_T      nSize;HWND        hWnd;BOOL        isActive;LRESULT     lResult;DWORD_PTR   lpStatus;struct __STMO_MSGEVENT* pNext[1];
} STMO_MSGEVENT, * LPSTMO_MSGEVENT;LPSTMO_MSGEVENT CreateNode(HWND hWnd, BOOL isActive, LRESULT lResult, DWORD_PTR lpStatus, SIZE_T nCount) {LPSTMO_MSGEVENT newNode = (LPSTMO_MSGEVENT)malloc(sizeof(STMO_MSGEVENT));newNode->nCount = nCount;newNode->nSize = 1;newNode->hWnd = hWnd;newNode->isActive = isActive;newNode->lResult = lResult;newNode->lpStatus = lpStatus;return newNode;
}LPSTMO_MSGEVENT InitializeList(SIZE_T initialSize) {LPSTMO_MSGEVENT newList = (LPSTMO_MSGEVENT)malloc(sizeof(STMO_MSGEVENT) + initialSize * sizeof(LPSTMO_MSGEVENT));if (newList != NULL) {memset(newList, 0, sizeof(LPSTMO_MSGEVENT) * initialSize + sizeof(STMO_MSGEVENT));newList->nCount = 1;newList->nSize = initialSize;newList->hWnd = NULL;newList->isActive = FALSE;newList->lResult = 0;newList->lpStatus = 0;return newList;}else {printf("Failed to allocate memory for the list.\n");return NULL;}
}void AddNode(LPSTMO_MSGEVENT* pList, HWND hWnd, BOOL isActive, LRESULT lResult, DWORD_PTR lpStatus) {LPSTMO_MSGEVENT newNode = CreateNode(hWnd, isActive, lResult, lpStatus, (*pList)->nCount);  // 也可以固定為 nSize,這只是一個記錄if ((*pList)->nCount < (*pList)->nSize) {(*pList)->pNext[(*pList)->nCount] = newNode;(*pList)->nCount++;}else {SIZE_T newSize = (*pList)->nSize * 2;LPSTMO_MSGEVENT newList = (LPSTMO_MSGEVENT)realloc(*pList, sizeof(STMO_MSGEVENT) + newSize * sizeof(LPSTMO_MSGEVENT));if (newList != NULL) {memset(newList, 0, sizeof(LPSTMO_MSGEVENT) * newSize + sizeof(STMO_MSGEVENT));*pList = newList;(*pList)->pNext[(*pList)->nCount] = newNode;(*pList)->nCount++;(*pList)->nSize = newSize;}else {free(newNode);printf("Failed to allocate memory for the new node.\n");}}
}void TraverseList(LPSTMO_MSGEVENT pList) {for (SIZE_T i = 0; i < pList->nCount; i++) {LPSTMO_MSGEVENT pNode = pList->pNext[i];std::cout << "index: 0x" << i << std::endl;std::cout << "hWnd: " << pNode->hWnd << std::endl;std::cout << "isActive: " << (pNode->isActive ? "true" : "false") << std::endl;std::cout << "lResult: " << pNode->lResult << "  lpStatus: " << pNode->lpStatus << std::endl;}
}void FreeList(LPSTMO_MSGEVENT* pList) {for (SIZE_T i = 0; i < (*pList)->nCount; i++) {free((*pList)->pNext[i]);}free(*pList);*pList = NULL;
}// Function to send message to a window using SendMessageTimeout
void SendMessageToWindow(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LPSTMO_MSGEVENT* lpstmoMsg)
{// Set the timeout value (in milliseconds)DWORD timeout = 5000;// Call ChangeWindowsMessageFilterEx to modify the message filterChangeWindowMessageFilterEx(hwnd, uMsg, MSGFLT_ALLOW, 0);// Send the message using SendMessageTimeoutDWORD_PTR lpStatus = 0;LRESULT   lResult = 0;lResult = SendMessageTimeoutW(hwnd, uMsg, wParam, lParam, SMTO_ABORTIFHUNG, timeout, &lpStatus);bool oldCount = lResult > 0 ? true : false;AddNode(lpstmoMsg, hwnd, oldCount, lResult, lpStatus);}// 該字符串消息使用系統(tǒng)原子表,返回值是 IntAtom 編號,
// 一般情況下在計算機重啟時才刷新。
UINT QueryTaskbarCreateMsg()
{return RegisterWindowMessageW(L"TaskbarCreated");
}// Callback function for window enumeration
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{// Cast the lParam to a vector of HWND pointersstd::vector<HWND>* windowList = reinterpret_cast<std::vector<HWND>*>(lParam);// Add the window handle to the vectorwindowList->push_back(hwnd);// Enumerate child windowsEnumChildWindows(hwnd, EnumWindowsProc, lParam);// Continue enumerationreturn TRUE;
}int main()
{// Enumerate all windowsstd::vector<HWND> windowList;EnumWindows(EnumWindowsProc, reinterpret_cast<LPARAM>(&windowList));// 要刷新任務欄的話用這個消息即可UINT uTaskbarMsg = QueryTaskbarCreateMsg();std::cout << "TaskbarCreateMsgAtom: 0x" << std::hex << uTaskbarMsg << std::endl;HWND hWnd = FindWindowW(L"Shell_TrayWnd", nullptr);// Create a vector of threadsstd::vector<std::thread> threads;UINT uMsg = WM_SETTINGCHANGE; // uTaskbarMsg;WPARAM wParam = (WPARAM)0;    // hWnd;LPARAM lParam = 0;LPSTMO_MSGEVENT msgev = InitializeList(1024);// Launch threads to send messages to windowsfor (HWND hwnd : windowList){// Create a thread and pass the window handle as an argumentthreads.emplace_back(SendMessageToWindow, hwnd, uMsg, wParam, lParam, &msgev);}// Wait for all threads to finishfor (std::thread& thread : threads){thread.join();}// Traverse and print the listprintf("List contents:\n");TraverseList(msgev);// Free the listFreeList(&msgev);return 0;
}

P.S. : 為了便于測試,我們選用了任務欄重建時的 TaskbarCreated 消息作為示例(這只會通知更新托盤圖標),如果要全局通知系統(tǒng)設置更改應該用?WM_SETTINGCHANGE 消息,但由于?WM_SETTINGCHANGE 是一瞬間的,不方便截圖,所以我只給出了 Taskbar Create 消息測試的結(jié)果。但是在上面的代碼中,我使用??WM_SETTINGCHANGE ,并注釋了?Taskbar Create 消息。

操作需要提升管理員權(quán)限,否則部分窗口可能因為 UIPI 過濾而無法接收到消息

我們開起了一個托盤圖標窗口程序,用于在接收到 TASKBAR_CREATED 消息時彈出消息框。

使用上文代碼工具廣播消息時,程序成功受到廣播的信息:

廣播結(jié)果截圖

測試程序的圖標

本文屬于原創(chuàng)文章,轉(zhuǎn)載請注明出處:

https://blog.csdn.net/qq_59075481/article/details/136175227。

文章發(fā)布于:2024.02.19,更新于:2024.02.20。

http://www.risenshineclean.com/news/56656.html

相關文章:

  • angular2是做網(wǎng)站的還是手機的百度風云榜小說排行榜歷屆榜單
  • 沒有備案的網(wǎng)站怎么做淘寶客產(chǎn)品軟文范例800字
  • 網(wǎng)站后臺管理系統(tǒng)下載360公司官網(wǎng)首頁
  • 網(wǎng)站建設專業(yè)課程網(wǎng)絡營銷與策劃
  • 網(wǎng)站只有一個首頁單頁面怎么做排名域名官網(wǎng)
  • 做網(wǎng)站app需要多少錢百度推廣運營
  • 談談對網(wǎng)站開發(fā)的理解站長工具seo綜合查詢怎么使用的
  • wordpress網(wǎng)站全過程谷歌seo最好的公司
  • 微信小程序外聯(lián)網(wǎng)站品牌廣告視頻
  • 微信開發(fā)者中心aso優(yōu)化貼吧
  • 部隊網(wǎng)站建設多少錢東莞網(wǎng)站seo公司哪家大
  • 網(wǎng)站建設合作流程搜索app下載
  • 網(wǎng)站日常推廣怎么做整合營銷傳播方法包括
  • 域名購買網(wǎng)站網(wǎng)絡銷售是干嘛的
  • 珠海百度推廣優(yōu)化seo排名優(yōu)化資源
  • 網(wǎng)站懸浮代碼成都網(wǎng)站推廣
  • 網(wǎng)站建設費用推薦網(wǎng)絡專業(yè)網(wǎng)絡服務商電話
  • 網(wǎng)站建設改版升級seo雙標題軟件
  • 網(wǎng)站開發(fā)哪里關鍵詞搜索技巧
  • wordpress 導入 附件seo系統(tǒng)源碼
  • 做網(wǎng)站前臺需要什么技能模板網(wǎng)站建設
  • 網(wǎng)站設計制作費用google網(wǎng)頁版
  • 外包推廣服務搜索引擎優(yōu)化專員
  • 做網(wǎng)站用那一種語言最好推廣營銷
  • 百度廣告平臺河北seo推廣
  • 教做面包的網(wǎng)站seo營銷方案
  • 旅行社建網(wǎng)站如何自己做網(wǎng)站
  • wordpress香港主機推薦北京seo排名廠家
  • nat123做網(wǎng)站廈門百度快速優(yōu)化排名
  • 做的網(wǎng)站手機打不開怎么回事啊徐州網(wǎng)站建設