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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

Windows消息机制学习笔记(二)—— 窗口与线程

發布時間:2025/3/21 windows 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Windows消息机制学习笔记(二)—— 窗口与线程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Windows消息機制學習筆記(二)—— 窗口與線程

    • 要點回顧
    • 消息從哪里來?
      • 實驗一:Spy++捕獲消息
      • 實驗二:消息捕獲
    • 消息到哪里去?
    • 窗口在哪?
      • 實驗:分析CreateWindowExW
    • 窗口對象
    • 總結

要點回顧

一個GUI線程對應一個消息隊列

本篇要解決的問題:

  • 消息從哪里來?
  • 消息到哪里去?
  • 誰來做這些事情?
  • 消息從哪里來?

    1)Spy++ 捕捉消息:鼠標消息、鍵盤消息
    2)程序發送消息

    實驗一:Spy++捕獲消息

    1)編譯并運行以下代碼

    #include <windows.h>LRESULT CALLBACK WindowProc(IN HWND hwnd,IN UINT uMsg,IN WPARAM wParam,IN LPARAM lParam ){return DefWindowProc(hwnd, uMsg, wParam, lParam); }int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd ){//窗口的類名TCHAR className[] = "My First Window";//創建一個自己的窗口WNDCLASS wndclass = {0};wndclass.hbrBackground = (HBRUSH)COLOR_MENU;wndclass.lpfnWndProc = WindowProc;wndclass.lpszClassName = className;wndclass.hInstance = hInstance;//注冊RegisterClass(&wndclass);//創建窗口HWND hwnd = CreateWindow(className,TEXT("我的第一個窗口"),WS_OVERLAPPEDWINDOW,10,10,600,300,NULL,NULL,hInstance,NULL);if(hwnd == NULL)return 0;//顯示窗口ShowWindow(hwnd, SW_SHOW);//消息循環MSG msg;while(GetMessage(&msg, NULL, 0, 0)){TranslateMessage(&msg);DispatchMessage(&msg);}return 0; }

    運行結果

    2)使用spy++定位窗口



    3)在窗口中進行任意操作,例如鼠標移動,鼠標點擊,鍵盤敲擊等,觀察消息列表

    實驗二:消息捕獲

    1)進程A運行以下代碼

    #include <windows.h>LRESULT CALLBACK WindowProc(IN HWND hwnd,IN UINT uMsg,IN WPARAM wParam,IN LPARAM lParam ){switch(uMsg){case 0x401:MessageBoxA(NULL, "接收到消息", "新消息", MB_OK);return false;}return DefWindowProc(hwnd, uMsg, wParam, lParam); }int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd ){//窗口的類名TCHAR className[] = "My First Window";//創建一個自己的窗口WNDCLASS wndclass = {0};wndclass.hbrBackground = (HBRUSH)COLOR_MENU;wndclass.lpfnWndProc = WindowProc;wndclass.lpszClassName = className;wndclass.hInstance = hInstance;//注冊RegisterClass(&wndclass);//創建窗口HWND hwnd = CreateWindow(className,TEXT("我的第一個窗口"),WS_OVERLAPPEDWINDOW,10,10,600,300,NULL,NULL,hInstance,NULL);if(hwnd == NULL)return 0;//顯示窗口ShowWindow(hwnd, SW_SHOW);//消息循環MSG msg;while(GetMessage(&msg, NULL, 0, 0)){TranslateMessage(&msg);DispatchMessage(&msg);}return 0; }

    2)進程B運行以下代碼

    #include <stdio.h> #include <windows.h>int main() {HWND hwnd = FindWindow("My First Window", "我的第一個窗口");SendMessage(hwnd, 0x401, 0, 0);return 0; }

    執行結果

    消息到哪里去?

    描述

  • 當我們使用鼠標某個窗口進行點擊與滑動時,都會產生一個消息,消息會進入當前窗口對應線程的消息隊列中
  • 當我們編寫程序時,并不會去特地啟動兩個線程去監控鼠標和鍵盤,w32k.sys負責了這個事情
  • 當初始化w32k.sys這個模塊時,會調用一個叫做InitInputImpl的函數
    這個函數會啟動兩個線程,分別用來監控鼠標和鍵盤,這兩個線程都是0環的線程
    平時我們的電腦遭遇“死機”時,常常是屏幕動不了,鼠標還能動,這正式由于鼠標是有一個獨立的線程在監控它的行動

    //FROM ReactOS v3.12 InitInputImpl(VOID) {...Status = PsCreateSystemThread(&RawInputThreadHandle, //監控鼠標THREAD_ALL_ACCESS,NULL,NULL,&RawInputThreadId,RawInputThreadMain,NULL);if (!NT_SUCCESS(Status)){DPRINT1("Win32K: Failed to create raw thread.\n");}Status = PsCreateSystemThread(&KeyboardThreadHandle, //監控鍵盤THREAD_ALL_ACCESS,NULL,NULL,&KeyboardThreadId,KeyboardThreadMain,NULL);if (!NT_SUCCESS(Status)){DPRINT1("Win32K: Failed to create keyboard thread.\n");}... }

    思考w32k.sys如何區分用戶點擊的是哪個窗口/消息要去哪個線程

    窗口在哪?

    當調用CreateWindow時,該函數實際上是一個宏,其CreateWindowA實際對應CreateWindowExA函數,CreateWindowW對應CreateWindowExW函數,可在編輯器中跟蹤觀察

    實驗:分析CreateWindowExW

    函數位于user32.dll
    總結:窗口在0環被畫出(由w32k.sys實現)

    窗口對象

    描述

  • 每個窗口對應一個WINDOW_OBJECT結構體,位于0環,包含當前窗口所有信息
  • 除了大窗口之外,窗口中的每個控件也都是一個窗口,也分別對應一個WINDOW_OBJECT結構體
  • 一個窗口內包含著許多個窗口,按鈕,對話框也都屬于窗口,屬于同一個線程
  • 一個線程可以包含多個窗口,但每個窗口只能屬于一個線程
  • //FROM ReactOS v3.12 typedef struct _WINDOW_OBJECT {...PWND Wnd; //包含大量窗口信息PTHREADINFO pti; //線程... } //FROM ReactOS v3.12 typedef struct _WND {.../* Style. */DWORD style; //包含窗口風格/后一個窗口/前一個窗口/父窗口/子窗口等信息... } WND, *PWND;

    消息進入窗口消息隊列的過程

  • 當使用鼠標在某個窗口上點擊時,鼠標監控線程檢測到點擊的窗口對象
  • 根據窗口對象成員,找到窗口對應線程
  • 將消息放入該線程的消息隊列中
  • 注意:在3環得到的窗口的句柄只是一個索引(參考句柄表章節)

    總結

  • 窗口在0環創建
  • 窗口句柄是全局的
  • 一個線程可以使用多個窗口,但每個窗口只能屬于一個線程
  • 總結

    以上是生活随笔為你收集整理的Windows消息机制学习笔记(二)—— 窗口与线程的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。