スクロールバーについて学んだところで、スクロールバーの位置パラメータをウィンドウのパラメータに当てはめたらウィンドウを間接的に操作できないだろうかと思い試しています。
こちらのサイトを参考に、まずはウィンドウを固定するプログラムを参考にしながら書き足してみたのですがウィンドウを移動しようとするとウィンドウが消えてしまいます。
次のプログラムが現在書いているものです。
#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()を返したところで消えているようなのですがなぜ消えてしまうのでしょうか。
上でリンクした参考サイトのサンプルでは問題なく動作しました。
もし原因の分かる方がいらっしゃいましたらご教示いただけると幸いです。
何卒よろしくお願いいたします。