win32APIでウィンドウの位置やサイズを固定したいのですが、ウィンドウを移動するとウィンドウが消えてしまいます。

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
kerotan0820
記事: 91
登録日時: 14年前

win32APIでウィンドウの位置やサイズを固定したいのですが、ウィンドウを移動するとウィンドウが消えてしまいます。

#1

投稿記事 by kerotan0820 » 10年前

VisualStudio2014にてwin32apiを勉強しております。
スクロールバーについて学んだところで、スクロールバーの位置パラメータをウィンドウのパラメータに当てはめたらウィンドウを間接的に操作できないだろうかと思い試しています。

こちらのサイトを参考に、まずはウィンドウを固定するプログラムを参考にしながら書き足してみたのですがウィンドウを移動しようとするとウィンドウが消えてしまいます。

次のプログラムが現在書いているものです。

コード:

#include <stdio.h>
#include <windows.h>

// 定数
#define IDC_SCRL 101        // スクロールバーのID

// グローバル変数
int vpos[2];                // スクロールの位置
int vmin = 0, vmax = 500;
char *sbtype[] = { "Window", "Control" };
RECT windowPos;
// 
HWND hMwnd, hCwnd, hScrl, hText[2];

// プロトタイプ宣言
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);


int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int nCmdShow)
{
	MSG        msg;
	WNDCLASSEX wndclass;
	SCROLLINFO si;
	char       str[100];
	int        i;

	vpos[0] = vpos[1] = 50;

	// ウィンドウクラスの定義
	wndclass.cbSize = sizeof(WNDCLASSEX);
	wndclass.style = CS_HREDRAW | CS_VREDRAW;
	//wndclass.style = 0;
	wndclass.lpfnWndProc = WndProc;
	wndclass.cbClsExtra = 0;
	wndclass.cbWndExtra = 0;
	wndclass.hInstance = hInstance;
	wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	wndclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
	wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
	wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	wndclass.lpszMenuName = NULL;
	wndclass.lpszClassName = "scroll";

	// --ウィンドウクラスの登録(出来なければ終了)
	if (!RegisterClassEx(&wndclass)) return 0;

	// --ウィンドウの生成
	windowPos.left = CW_USEDEFAULT;
	windowPos.top = CW_USEDEFAULT;
	windowPos.right = 400;
	windowPos.bottom = 200;

	hMwnd = CreateWindow("scroll",        // ウィンドウクラスの名前
		"Scrollbar Example",              // ウィンドウのタイトル
		WS_OVERLAPPEDWINDOW |             // ウィンドウのスタイル
		WS_VSCROLL,                       // WS_VSCROLLを追加
		windowPos.left, windowPos.top,    // ウィンドウの作成位置(x,y)
		windowPos.right, windowPos.bottom,// ウィンドウのサイズ(w,h)
		HWND_DESKTOP,                     // 親ウィンドウのハンドル
		NULL,                             // メインメニューのハンドル
		hInstance,                        // アプリケーションインスタンスのハンドル
		NULL);                            // 追加情報へのポインタ

	// --スクロールバーの作成
	hScrl = CreateWindow("SCROLLBAR", "", // 
		WS_CHILD | WS_VISIBLE | SBS_VERT,
		340, 10, 20, 150,
		hMwnd,
		(HMENU)IDC_SCRL,                       // IDを設定しているが本プログラムでは使わない
		hInstance, NULL);

	si.cbSize = sizeof(SCROLLINFO);            // スクロール情報構造体の設定
	si.fMask = SIF_POS | SIF_RANGE | SIF_PAGE; // 位置、範囲、つまみの大きさを指定
	si.nPos = vpos[0];                         // 位置
	si.nMin = vmin;                            // 範囲
	si.nMax = vmax;                            //
	si.nPage = 1;                              // ページサイズ、つまみの大きさ

	SetScrollInfo(hMwnd, SB_VERT, &si, FALSE);
	SetScrollInfo(hScrl, SB_CTL, &si, FALSE);

	for (i = 0; i < 2; i++){                   // スクロール状態を表示するコントロールを貼る
		wsprintf(str, "ScrollBar(%s) Position : %3d\n", sbtype[i], vpos[i]);
		hText[i] = CreateWindow("static",
			str,
			WS_CHILD | WS_VISIBLE | SS_LEFT,
			10, 10 + i * 20, 300, 20,              // 位置(x,y), サイズ(w,h)
			hMwnd,
			NULL, hInstance, NULL);
	}
	/*
	hCwnd = CreateWindow("scroll",
		"子ウィンドウ",
		WS_OVERLAPPEDWINDOW,
		vpos[0], vpos[1], 180, 90,                     // 位置(x,y), サイズ(w,h)
		hMwnd,
		NULL, hInstance, NULL);
*/
	ShowWindow(hMwnd, nCmdShow);               // SetScrollInfo()の後、表示する
	UpdateWindow(hMwnd);
//	ShowWindow(hCwnd, nCmdShow);
//	UpdateWindow(hMwnd);

	// メッセージループ
	while (GetMessage(&msg, NULL, 0, 0)){
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
	SCROLLINFO si;
	int        i;
	char   str[100];
	//	char debug[50];

	switch (iMessage){
	case WM_VSCROLL:
		// ウィンドウのスクロールバーとコントロールの区別
		if (lParam == 0) i = 0;                // ウィンドウのスクロールバーの場合
		else i = 1;

		//		wsprintf(debug, "lParam = %d", lParam);
		//		MessageBox(HWND_DESKTOP, debug, "DEBUG", MB_OK);

		switch (LOWORD(wParam)){
		case SB_LINEUP:                        // ▲が押されたとき
			vpos[i] --;
			if (vpos[i] < vmin) vpos[i] = vmin;
			break;
		case SB_LINEDOWN:                      // ▼が押されたとき
			vpos[i] ++;
			if (vpos[i] > vmax) vpos[i] = vmax;
			break;
		case SB_PAGEUP:                        // ▲とつまみの間が押されたとき
			vpos[i] -= 5;
			if (vpos[i] < vmin) vpos[i] = vmin;
			break;
		case SB_PAGEDOWN:                      // ▼とつまみの間が押されたとき
			vpos[i] += 5;
			if (vpos[i] > vmax) vpos[i] = vmax;
			break;
		case SB_THUMBTRACK:                    // つまみをドラッグ中
			vpos[i] = HIWORD(wParam);
			break;
		case SB_THUMBPOSITION:                 // つまみを放したとき
			vpos[i] = HIWORD(wParam);
			break;
		}
		// スクロールバーのパラメータにあわせて子ウィンドウのサイズを変更

		// パラメータを計算してからSetScrollInfoでつまみを動かす
		si.cbSize = sizeof(SCROLLINFO);
		si.fMask = SIF_POS;
		si.nPos = vpos[i];
		if (lParam == 0)
			SetScrollInfo(hWnd, SB_VERT, &si, TRUE);
		else
			SetScrollInfo((HWND)lParam, SB_CTL, &si, TRUE);

		wsprintf(str, "ScrollBar(%s) Position : %3d", sbtype[i], vpos[i]);
		SetWindowText(hText[i], str);
		break;

	case WM_MOVING:
		((RECT*)lParam)->left = windowPos.left;
		((RECT*)lParam)->top = windowPos.top;
		((RECT*)lParam)->right = windowPos.right;
		((RECT*)lParam)->bottom = windowPos.bottom;
		break;

	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	}
	return DefWindowProc(hWnd, iMessage, wParam, lParam);
}

どの段階でウィンドウが消えるのかを確認したところ、
CALLBACK WndProc関数のDefWindowProc()を返したところで消えているようなのですがなぜ消えてしまうのでしょうか。

上でリンクした参考サイトのサンプルでは問題なく動作しました。

もし原因の分かる方がいらっしゃいましたらご教示いただけると幸いです。
何卒よろしくお願いいたします。
けろけろにゃー (」・ω・)」うー!

アバター
へにっくす
記事: 634
登録日時: 13年前
住所: 東京都

Re: win32APIでウィンドウの位置やサイズを固定したいのですが、ウィンドウを移動するとウィンドウが消えてしまいま

#2

投稿記事 by へにっくす » 10年前

CW_USEDEFAULTがどういう値か調べてください。
また、CreateWindowに渡すものとWM_MOVINGで渡すものは同じではありません。

上でリンクしたサンプルのほうで、CW_USEDEFAULTは使われていませんよね。
またrightとbottomに幅と高さをそのまま代入してませんよね。

ちゃんと理解しましょう。
written by へにっくす

kerotan0820
記事: 91
登録日時: 14年前

Re: win32APIでウィンドウの位置やサイズを固定したいのですが、ウィンドウを移動するとウィンドウが消えてしまいま

#3

投稿記事 by kerotan0820 » 10年前

[quote="へにっくす" id=3,16357,128882]

回答ありがとうございます。

CW_USEDEFAULTの値を調べたところ、 0x800000000 という値でウィンドウズに自動でウィンドウサイズを指定させるためのパラメータに過ぎないということが分かりました。
ウィンドウサイズをきちんと明示したところウィンドウが消えることはなくなりました。

以降曖昧な点はきちんと調べるようにしたいと思います。

ありがとうございました。
けろけろにゃー (」・ω・)」うー!

閉鎖

“C言語何でも質問掲示板” へ戻る