WinXP VC++6.0 SDK
はじめまして。
エディットコントロールのようなものを自作しようと思いまして、
まず、キーボードの押された文字を表示するだけのプログラムを作りました。
しかし、親ウィンドウに、その子ウィンドウを2つ以上貼り付けると、
2つに書かれている文字列が同じになってしまいます。
エディットコントロールのように2つ以上貼り付けても、違う文字列を表示するには
どうすればよいのでしょうか。
//押された文字を表示するソース
static HWND hEdit1, hEdit2;
WNDCLASS wc;
case WM_CREATE:
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = EditProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_IBEAM);
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = "EditTest";
RegisterClass(&wc);
hEdit1 = CreateWindow("EditTest", NULL,
WS_CHILD | WS_VISIBLE,
0, 0, 0, 0, hWnd, (HMENU)150, hInstance, NULL);
hEdit2 = CreateWindow("EditTest", NULL,
WS_CHILD | WS_VISIBLE,
0, 0, 0, 0, hWnd, (HMENU)151, hInstance, NULL);
break;
//省略
LRESULT CALLBACK EditProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static char szText[1000];
//省略
case WM_CHAR:
wsprintf(szText, "%s%c", szText, wParam);
InvalidateRect(hWnd, NULL, FALSE);
break;
case WM_PAINT:
hDC = BeginPaint(hWnd, &ps);
TextOut(0, 0, szText, lstrlen(szText));
EndPaint(hWnd, &ps);
break;
//<省略
szTextをstaticにしたのはなぜですか?
ちゃんと考えれば,szTextがstaticではまずいことはわかるはずです。
WNDCLASS::cbWndExtraで用意したエクストラ領域を使って,
それぞれのコントロールの情報をコントロールごとに保持させる必要があります。
ウィンドウごとに、テキストを覚えておく領域を別にすればよいのではないでしょうか。
現状、2つのウィンドウはウィンドウプロシージャを共有し、その中にある szText も共有しています。
これを、ウィンドウごとに個別のデータ領域にテキストを記憶させておけばよいと思われます。
cbWndExtra か SetProp などを活用してみては?
かぶった^^;;
返答ありがとうございます。
cbWndExtraのヘルプを見てみました。
しかしながら、cbWndExtraで割り当てたエクストラ領域に個別のデータを
どのように記憶させるのでしょうか。
見当違いなことを言っているかもしれませんが、おねがいします。
SetWindowLong を使います。
このソースの場合
wc.cbWndExtra = 0;
を
wc.cbWndExtra = 1000;
に変え、
EditProcのWM_CREATEの初めに
SetWindowLong(hWnd, 0, (LONG)&szText);
と書けばよいのでしょうか。
遅レス。
> と書けばよいのでしょうか。
それはたぶん違うだろうな…と思いつつ、そんなことしたことがなかったのでデマ言っちゃマズいと、自分でも試してみることに。
子ウィンドウにフォーカスが来ない。何故だ…
何か初歩的なことで詰まっている気がしてならないなぁ。
というわけで、若干自信喪失気味な予測でよろしければ。
まず、cbWndExtra はたぶん 4。
で、SetWindowLong で設定する値は、malloc なり new なりで動的に確保する。もちろん、終了時に破棄を忘れずに。
現状、なぜ static なのかといえば、EditProc から抜けた後でも値を保持させ続けたいからでしょう。
が、そのために、2つのウィンドウプロシージャで変数を共有してしまっている。
static にしちゃダメなんだけど、EditProc から抜けた後でも値を保持させ続けたいならば…子ウィンドウが存在する限り終わらない関数(つまり WinMain)で宣言するか、あるいは動的に確保するか。個人的には後者がオススメです。
> wc.cbWndExtra = 1000;
どこまで取れるのか確認したことはありませんが、
この領域をあまり大きくとるのは多分よろしくありませんから、
文字バッファを直接とるのはやめた方がいいと思います。
> SetWindowLong(hWnd, 0, (LONG)&szText);
ではそう使ってませんけど(単に無駄領域)。
> というわけで、若干自信喪失気味な予測でよろしければ。
> まず、cbWndExtra はたぶん 4。
ポインタを格納するだけならポインタのサイズでいいはずです。
一応(Win64等も考えると)即値よりは sizeof をお勧めします。
用法にもよりますが、GWL_USERDATA でも十分な気が。
ツイート | ![]() |