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

歡迎訪問 生活随笔!

生活随笔

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

windows

Windows消息机制学习笔记(一)—— 消息队列

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

Windows消息機制學習筆記(一)—— 消息隊列

    • 基本概念
    • 實驗一:使用代碼畫出最簡單窗口
      • 第一步:編譯并運行以下代碼
      • 第二步:查看運行結(jié)果
      • 第三步:使用其它窗口對其進行覆蓋,觀察效果
      • 總結(jié)
    • 消息隊列
      • 消息隊列在哪
        • Linux:專用進程
        • Windows:GUI線程
      • Win32Thread
    • 總結(jié)

基本概念

接觸過編程的人,或多或少用到過消息機制,但大多數(shù)人(包括我自己)只是知道相關API的基本用法,卻不知道它是如何實現(xiàn)的

從本章起,我們將帶著以下幾個問題一起來學習消息機制:

  • 什么是窗口句柄?在哪里?有什么用?
  • 什么是消息?什么是消息隊列?消息隊列在哪?
  • 什么是窗口過程?窗口過程是誰調(diào)用的?沒有消息循環(huán)窗口過程會執(zhí)行嗎?
  • 為什么要有w32k.sys這個模塊?
  • 為什么只有使用圖形界面的程序才可以訪問KeServiceDescriptorTableShadow?
  • 界面"卡死"的時候為什么鼠標還可以動?
  • 實驗一:使用代碼畫出最簡單窗口

    第一步:編譯并運行以下代碼

    #include <stdio.h> #define _WIN32_WINNT 0x500 #include <windows.h>typedef struct _Color {DWORD r;DWORD g;DWORD b; }Color;typedef struct _WindowClass {DWORD x;DWORD y;DWORD width;DWORD height;Color color; }WindowClass;//按照WindowClass的參數(shù),將hdc中的數(shù)據(jù)打印到指定設備 void PaintWindows(HDC hdc, WindowClass *p) {HBRUSH hBrush;hBrush = (HBRUSH)GetStockObject(DC_BRUSH);SelectObject(hdc, hBrush); //畫刷SetDCBrushColor(hdc, RGB(p->color.r, p->color.g, p->color.b));MoveToEx(hdc, p->x, p->y, NULL);LineTo(hdc, p->x+p->width, p->y);LineTo(hdc, p->x+p->width, p->y+p->height);LineTo(hdc, p->x, p->y+p->height);LineTo(hdc, p->x, p->y);Rectangle(hdc, p->x, p->y, p->width, p->height+1);DeleteObject(hBrush); }int main() {char cMessage; //消息HWND hwnd; //畫在哪HDC hdc; //顯卡緩存//設置窗口參數(shù),長寬高之類的WindowClass wClass;wClass.x = 0;wClass.y = 0;wClass.width = 800;wClass.height = 400;wClass.color.r = 0xEF;wClass.color.g = 0xEB;wClass.color.b = 0xDE;//畫在哪hwnd = GetDesktopWindow();//hwnd = FindWindow("dbgviewClass", NULL);//獲取DC設備句柄:可以把DC理解成顯卡緩存hdc = GetWindowDC(hwnd);for(;;){//畫窗口PaintWindows(hdc, &wClass);cMessage = getchar();switch(cMessage){case 'a':wClass.color.r += 0x10;wClass.color.g += 0x10;wClass.color.b += 0x10;break;case 'b':wClass.color.r -= 0x10;wClass.color.g -= 0x10;wClass.color.b -= 0x10;break;}}return 0; }

    第二步:查看運行結(jié)果

    第三步:使用其它窗口對其進行覆蓋,觀察效果

    總結(jié)

  • 畫出的部分被其它窗口覆蓋后就消失了
  • 手動畫出的窗口只能接收鍵盤發(fā)送的消息
  • 思考:如何使窗口能夠接收所有消息
    答案:將所有消息放入一塊內(nèi)存中,這塊內(nèi)存被稱之為“消息隊列

    消息隊列

    描述:本質(zhì)上是一種數(shù)據(jù)結(jié)構,當對象接收到消息時,將接收到的所有消息放入消息隊列中,等待對象進行處理
    規(guī)則:先進先出

    消息隊列在哪

    Linux:專用進程

  • 使用專用進程捕獲所有消息
  • 判斷消息所屬進程,進行分發(fā),將消息分配到目標進程的消息隊列中
  • Windows:GUI線程

    查看KTHREAD結(jié)構體

    kd> dt _KTHREAD ntdll!_KTHREAD...+0x130 Win32Thread //若當前程序為控制臺程序且無使用任何圖形界面相關API,該成員為空//若當前程序使用了圖形界面相關的API,該成員指向一個結(jié)構體,該結(jié)構體包含了消息隊列...

    GUI:微軟提供的與圖形界面相關的API,稱為GUI
    GDI:自定義的用于圖形界面相關的API,稱為GDI

    GUI線程

  • 當線程剛創(chuàng)建的時候,都是普通線程:
    Thread.ServiceTable指向KeServiceDescriptorTable
  • 當線程第一次調(diào)用Win32k.sys(調(diào)用號大于0x100)時,會調(diào)用一個函數(shù),將當前線程轉(zhuǎn)換成GUI線程:PsConvertToGuiThread
    主要做幾件事:
    a. 擴充內(nèi)核棧,必須換成64KB的大內(nèi)核棧,因為普通內(nèi)核棧只有12KB大小
    b.創(chuàng)建一個包含消息隊列的結(jié)構體,并掛到KTHREAD上
    c.將Thread.ServiceTable指向KeServiceDescriptorTableShadow(只有當調(diào)用GUI時,才會指向SSDTShadow)
    d.把需要的內(nèi)存數(shù)據(jù)映射到本進程空間
  • Win32Thread

    描述:位于KTHREAD,若當前程序使用了圖形界面相關的API,該成員指向一個結(jié)構體,其中包含了當前線程的消息隊列:THREADINFO

    //FROM ReactOS v0.4.13 typedef struct _THREADINFO{...struct _USER_MESSAGE_QUEUE* MessageQueue; //消息隊列... } THREADINFO;

    總結(jié)

  • 消息隊列存儲在0環(huán),通過KTHREAD.Win32Thread可以找到
  • 并不是所有線程都要消息隊列,只有GUI線程才有消息隊列
  • 一個GUI線程對應1個消息隊列
  • 總結(jié)

    以上是生活随笔為你收集整理的Windows消息机制学习笔记(一)—— 消息队列的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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