ご閲覧ありがとうございます。
前提・実現したいこと
Win32APIとC++でソフトウェアを作ろうとしています。
今はグローバル変数やstatic修飾子を使わずに設計できないかを試しています。
発生している問題・疑問
グローバル変数やstatic修飾子を一切使わない場合、ウィンドウプロシージャからはC++やwin32API標準の識別子以外不可視であると思います。
試したこと
■ウィンドウプロシージャに引数を追加する
WNDCLASS構造体が必要とするウィンドウプロシージャの型WNDPROCと型違いになる。
■ウィンドウプロシージャそのものを何らかのクラスのメソッドにする(例えばMyWindowクラスを定義してそのメソッドとする)
static修飾子を付加しない場合WNDCLASS構造体にウィンドウプロシージャのメソッド名を代入する部分でC3867非標準の構文となりました。
仕組み的にもシステムが使うであろうウィンドウプロシージャがインスタンスありきでは不都合に思えます。
staticを付記すれば動作しますが、これしか方法はないのでしょうか。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/02/16 02:33
回答4件
0
※質問は閉じてしまいましたが、サンプルコードを書いていたので、せっかくなので放流させていただきます。
様々な方法があると思いますが、SetWindowLongPtrとGetWindowLongPtrを利用し、インデックスGWLP_USERDATA
の位置にウィンドウ固有のユーザーデータ(へのポインタ)を格納して取り扱う例です。ここに収め、必要なときに参照することでウィンドウが生きている間、永続的に利用することができます。つまり、グローバル変数の代わりとして使えます。尚、GWL_USERDATA
ではくGWLP_USERDATA
を使うことで32ビット、64ビットどちらのビルドでも対応できます。(GWL_USERDATA
は32ビットのみ)
以下のサンプルでは独自クラスUserClass
のインスタンスへのポインタを収め、WM_PAINT
でのウィンドウ描画時にメンバー関数Increment
で値を更新し、画面に表示します。このコード上ではC言語/C++でのグローバル変数は使っていません。簡単なコードですので、ビルドして試してみてください。ウィンドウのサイズを変えると都度、WM_PAINT
が発生し、再描画されるはずです。
C++
1#include <Windows.h> 2 3#define WINDOWCLASSNAME "MyWindowClass" 4 5class UserClass { 6public: 7 UserClass() 8 : v_(0) { 9 } 10 11 int Increment() { 12 return ++v_; 13 } 14 15private: 16 int v_; 17}; 18 19LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); 20 21int APIENTRY wWinMain(_In_ HINSTANCE hInstance, 22 _In_opt_ HINSTANCE hPrevInstance, 23 _In_ LPWSTR lpCmdLine, 24 _In_ int nCmdShow) 25{ 26 UNREFERENCED_PARAMETER(hPrevInstance); 27 UNREFERENCED_PARAMETER(lpCmdLine); 28 29 WNDCLASSEXW wcex; 30 wcex.cbSize = sizeof(WNDCLASSEX); 31 wcex.style = CS_HREDRAW | CS_VREDRAW; 32 wcex.lpfnWndProc = WndProc; 33 wcex.cbClsExtra = 0; 34 wcex.cbWndExtra = 0; 35 wcex.hInstance = hInstance; 36 wcex.hIcon = NULL; 37 wcex.hCursor = LoadCursor(NULL, IDC_ARROW); 38 wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); 39 wcex.lpszMenuName = NULL; 40 wcex.lpszClassName = TEXT(WINDOWCLASSNAME); 41 wcex.hIconSm = NULL; 42 43 RegisterClassExW(&wcex); 44 45 HWND hWnd = CreateWindowW(TEXT(WINDOWCLASSNAME), L"Sample", WS_OVERLAPPEDWINDOW, 46 0, 0, 320, 240, NULL, NULL, hInstance, NULL); 47 48 if (!hWnd) 49 { 50 return FALSE; 51 } 52 53 UserClass* p = new UserClass(); 54 LONG_PTR ret = SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)p); 55 56 ShowWindow(hWnd, nCmdShow); 57 UpdateWindow(hWnd); 58 59 MSG msg; 60 61 while (GetMessage(&msg, NULL, 0, 0)) 62 { 63 TranslateMessage(&msg); 64 DispatchMessage(&msg); 65 } 66 67 return (int)msg.wParam; 68} 69 70LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 71{ 72 switch (message) { 73 case WM_PAINT: 74 { 75 PAINTSTRUCT ps; 76 WCHAR s[256]; 77 HDC hdc = BeginPaint(hWnd, &ps); 78 LONG_PTR p = GetWindowLongPtr(hWnd, GWLP_USERDATA); 79 if (p != NULL) { 80 UserClass* up = (UserClass*)(p); 81 int v = up->Increment(); 82 wsprintfW(s, L"v=%d", v); 83 } 84 else { 85 lstrcpyW(s, L"NONE"); 86 } 87 DrawTextW(hdc, s, -1, &ps.rcPaint, DT_LEFT); 88 EndPaint(hWnd, &ps); 89 } 90 break; 91 92 case WM_DESTROY: 93 { 94 LONG_PTR p = GetWindowLongPtr(hWnd, GWLP_USERDATA); 95 if (p != NULL) { 96 UserClass* up = (UserClass*)p; 97 delete up; 98 } 99 PostQuitMessage(0); 100 } 101 break; 102 103 default: 104 return DefWindowProc(hWnd, message, wParam, lParam); 105 } 106 107 return 0; 108}
投稿2021/02/16 07:03
編集2021/02/16 07:17総合スコア9256
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/02/16 07:08
2021/02/16 07:28
2021/02/16 07:36
2021/02/16 07:43
2021/02/16 07:46
2021/02/19 06:34
2021/02/19 07:41
0
ベストアンサー
ウィンドウハンドルと何かを紐づける手段 として SetProp
というAPIがあります.
これを使って何かしらのポインタ値を登録しておき,ウィンドウプロシージャ内で GetProp
で取り出して使うという方法があります.
(ポインタ値を登録するのは,「HANDLE
型のサイズ≧ポインタのサイズ」を暗黙的に前提としている形になるので,その点に微妙さはあるかも?)
投稿2021/02/16 02:47
総合スコア11996
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/02/16 02:50
2021/02/16 02:56
2021/02/16 03:00
2021/02/16 03:03
2021/02/16 03:10
2021/02/16 05:57
2021/02/16 06:21
0
https://sourceforge.net/projects/wtl/
WTLとかを参考にすると良いかも。
投稿2021/02/16 02:21
総合スコア5488
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。