Windows Programming - 1. A Simple Window
前言
在進入代碼環節之前,首先來思考一個問題,一個基本的桌面應用程序,包含了甚麼?
- 視窗: 用於顯示內容,包含菜單欄、圖標、名字等
- 消息循環器: 循環監聽消息發生
- 消息處理器: 包含了滑鼠、鍵盤的事件等的處理
也就是說,一個最基本的桌面應用程序包含了一個視窗以及一個消息體。
代碼說明
視窗的注冊及顯示
1 |
|
消息處理器
1 | LRESULT CALLBACK MsgProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { |
消息循環
1 | MSG msg = {}; |
在按照代碼輸入WNDCLASS
的時候,可能會被WNDCLASSA
、WNDCLASSEX
等的相似結構體所迷惑。根據微軟官方文檔的說法,WNDCLASS
已經全面被WNDCLASSEX
所取代。在新系統上的新功能,只能通過WNDCLASSEX
來設置。而WNDCLASSA
和WNDCLASSW
中的A與W的區別在於程序是否使用了Unicode。WNDCLASS
以及WNDCLASSEX
是Microsoft官方已經為用戶設計好的宏,根據用戶的配置來自動切換到A或W。其它還有很多類似存在EX、A和W的相似方法和結構體都是相似的原理。
除了PeekMessage()
外,還有GetMessage()
。GetMessage()
會一直等待直到有消息到來才有返回值,屬於阻塞函數。而PeekMessage
是以查看的方式從系統中獲取消息,屬於非阻塞函數。
UpdateWindow()
相當於執行一次Paint,會發送一次WM_PAINT
消息,而PeekMessage()
以及GetMessage()
也會生成WM_PAINT
消息。
AdjustWindowRect()
是因為在創建視窗時,最初所設置的window_width
以及window_height
是不包含窗單欄、邊框等的大小,所以需要使用AdjustWindowRect()
,根據視窗的類型來計算真實的視窗大小。
完整代碼
1 | LRESULT CALLBACK MsgProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { |
前書き
コードを見る前、サンプルなデスクトップアプリケーションではどのようなものが存在しているかを考えましょう。
- ウィンド: コンテンツを表示する
- メッセージループ: メッセージがあるかどうか確認する
- メッセージ処理機: メッセージにより、具体的な処理を行う
簡単に言うと、ウィンドとメッセージシステムがあります。
コードの説明
ウィンドの登録と表示
1 |
|
メッセージの処理機
1 | LRESULT CALLBACK MsgProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { |
メッセージループ
1 | MSG msg = {}; |
上のコードのような入力したら、WNDCLASSA
やWNDCLASSEX
などこういったキーワードに戸惑うかもしれません。公式の文書によりますと、WNDCLASS
は既にWNDCLASSEX
に置き換えられました。新Windowsの新機能はWNDCLASSEX
だけ設定できます。また、WNDCLASSA
とWNDCLASSW
のAとWの違いはプロジェクトがUnicodeを使用しているかどうかです。WNDCLASS
とWNDCLASSEX
は自動的にUnicodeを使用しているかどうかによって変わるdefineです。つまり、自動的にAかWかを決めます。他のxxxEX
、xxxA
、xxxW
はほとんど同じ意味です。
PeekMessage()
の以外、GetMessage()
が存在しています。GetMessage()
はずっとメッセージを待っていて、アプリケーションの運行が止まります。PeekMessage()
はシステムは今はメッセージがあるかを聞いて、運行が止まりません。
UpdateWindow()
は一回のPaintを行って、WM_PAINT
のメッセージを送ります。また、GetMessage()
とPeekMessage()
を行うと、WM_PAINT
を発想します。
AdjustWindowRect()
はウィンドの境界やメニューバーなどによって、ウィンドのサイぞを再計算します。
全コード
1 | LRESULT CALLBACK MsgProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { |