首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 組合語言

Win32 組合語言教學:處理滑鼠按鍵訊息(WM_LBUTTONDOWN)

     編輯:組合語言

教學目標

本篇教學示範在 Win32 視窗程序中處理滑鼠左鍵按下訊息(WM_LBUTTONDOWN),於點擊位置繪製字串。涵蓋訊息迴路、座標提取、無效區觸發重繪、WM_PAINT 繪圖流程等核心概念。

理論基礎:滑鼠訊息機制

  • Windows 將滑鼠事件封裝為訊息發送給「滑鼠游標所在視窗」,不受輸入焦點限制
  • 主要訊息:WM_LBUTTONDOWN/UP、WM_RBUTTONDOWN/UP、WM_MOUSEMOVE、WM_LBUTTONDBLCLK(需 CS_DBLCLKS 類別風格)
  • lParam 低 16 位 = x 座標,高 16 位 = y 座標(相對用戶區左上角)
  • wParam 指示修飾鍵狀態(Shift/Ctrl/滑鼠鍵)

範例程式架構(MASM32)

資料區

.data
ClassName db "SimpleWinClass",0
AppName   db "Our First Window",0
MouseClick db 0              ; 0=尚未點擊
.data?
hitpoint POINT <>           ; 儲存點擊座標

視窗程序關鍵片段

WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
  .IF uMsg==WM_LBUTTONDOWN
    ; 取出 x, y 座標
    MOV EAX, lParam
    AND EAX, 0FFFFh
    MOV hitpoint.x, EAX
    MOV EAX, lParam
    SHR EAX, 16
    MOV hitpoint.y, EAX
    MOV MouseClick, TRUE
    INVOKE InvalidateRect, hWnd, NULL, TRUE  ; 觸發 WM_PAINT
  .ELSEIF uMsg==WM_PAINT
    INVOKE BeginPaint, hWnd, ADDR ps
    MOV hdc, EAX
    .IF MouseClick
      INVOKE lstrlen, ADDR AppName
      INVOKE TextOut, hdc, hitpoint.x, hitpoint.y, ADDR AppName, EAX
    .ENDIF
    INVOKE EndPaint, hWnd, ADDR ps
  .ENDIF
  ...
WndProc endp

關鍵步驟解析

  1. 座標解碼:lParam 為 32 位有號整數,AND 0FFFFh 取低字(x),SHR 16 取高字(y)。
  2. 狀態標記:MouseClick 區分「首次顯示(無點擊)」與「有點擊需繪製」。
  3. 觸發重繪:InvalidateRect(hWnd, NULL, TRUE) 將整個用戶區標記為無效,並要求清除背景,Windows 隨後發送 WM_PAINT。
  4. 繪製邏輯集中於 WM_PAINT:唯有在 BeginPaint/EndPaint 之間呼叫 TextOut,才能確保視窗縮放、遮蔽還原時字串持續可見。

常見誤區與最佳實踐

  • ❌ 在 WM_LBUTTONDOWN 直接呼叫 GetDC/TextOut/ReleaseDC → 視窗重繪時字串消失
  • ✅ 所有持久化繪圖必須在 WM_PAINT 內完成,透過狀態變數傳遞參數
  • ✅ 使用 InvalidateRect / UpdateWindow 主動觸發重繪,而非手動繪圖

擴展練習

  • 支援右鍵顯示座標數值
  • 加入 WM_MOUSEMOVE 即時顯示游標位置
  • 使用 SetCapture/ReleaseCapture 實現拖曳繪圖
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved