今回はエディットにスクロールバーをつけます。
エディット - インコのWindowsSDK で作成したソースを修正します。
流れ
WM_CREATE
WM_CREATEは、ウインドウが生成されたときに1回だけ実行されます。
1.CreateWindowEx()のウインドウスタイルにWS_VSCROLLをつける。
2.GetSystemMetrics()で、モニタの画面全体の幅・高さを取得
WM_SIZE
1.SetScrollRange()で、スクロールボックス(つまみ)の最大位置と最小位置を設定。
BOOL SetScrollRange(
HWND hWnd, // ウィンドウのハンドル
int nBar, // スクロールバー
int nMinPos, // スクロールボックスの最小位置
int nMaxPos, // スクロールボックスの最大位置
BOOL bRedraw // 再描画フラグ(trueで再描画)
);
| nBar | 意味 |
|---|---|
| SB_CTL | スクロールバーコントロールで、最大位置と最小位置を設定 |
| SB_HORZ | 水平スクロールバーで、最大位置と最小位置を設定 |
| SB_VERT | 垂直スクロールバーで、最大位置と最小位置を設定 |
2.SetScrollPos()で、スクロールボックス(つまみ)の現在位置を設定。
int SetScrollPos(
int nBar, // スクロールバー
int nPos, // スクロールボックスの新しい位置
BOOL bRedraw // 再描画フラグ(trueで再描画)
);
| nBar | 意味 |
|---|---|
| SB_HORZ | 水平スクロールバーで、最大位置と最小位置を設定 |
| SB_VERT | 垂直スクロールバーで、最大位置と最小位置を設定 |
WM_VSCROLL
WM_VSCROLLメッセージは、垂直スクロールバーが操作されたとき実行されます。
● WM_VSCROLLメッセージ発生時のwParam
| wParamの下位ワード | 内容 |
|---|---|
| SB_LINEUP |
1 行上へスクロール スクロール・バーの両端にある三角形のついたボタンを押したとき |
| SB_LINEDOWN |
1 行下へスクロール スクロール・バーの両端にある三角形のついたボタンを押したとき |
| SB_PAGEUP |
1 ページ上へスクロール スクロール矢印とスクロールボックスの間を押したとき |
| SB_PAGEDOWN |
1 ページ下へスクロール スクロール矢印とスクロールボックスの間を押したとき |
| SB_THUMBPOSITION |
絶対位置へスクロール スクロールボックスが押されたとき wParamの下位ワードにスクロールボックスの現在位置を示します。 |
| SB_THUMTRACK |
指定位置へスクロール ボックスをドラッグ。 スクロールボックスが離されたとき wParamの下位ワードにスクロールボックスの現在位置を示します。 |
| SB_TOP | [HOME]キーが押された |
| SB_BOTTMOM | [END]キーが押された |
| SB_ENDSCROLL | スクロールが終了 |
wParamの上位ワード:SB_THUMPOSITIONとSB_THUMTRACKのときスクロールボックスの現在位置
● WM_VSCROLLメッセージ発生時のlParam:スクロールバーのハンドル
1.ScrollWindowで、クライアント領域の内容をスクロールします。
void ScrollWindow(
int xAmount, // 水平方向のスクロール量
int yAmount, // 垂直方向のスクロール量
LPCRECT lpRect, // スクロールするクライアント領域の部分(NULLで全体)
LPCRECT lpClipRect // スクロールするクリッピング四角形
);
2.SetScrollPos()で、スクロールボックス(つまみ)の現在位置を設定。
3.UpdateWindow()で、ウインドウを更新します。
ソースコードの入力
ソースコードは下記のように入れてください。
#include <windows.h>
#include "Resource.h"
// グローバル変数:
HINSTANCE hInst; // 現在のインターフェイス
// このコード モジュールに含まれる関数の宣言を転送します:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
MSG msg;
MyRegisterClass(hInstance);
// アプリケーションの初期化を実行します:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
// メイン メッセージ ループ:
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
}
//
// 関数: MyRegisterClass()
//
// 目的: ウィンドウ クラスを登録します。
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(NULL , IDI_APPLICATION);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_HP);
wcex.lpszClassName = TEXT("HP");
wcex.hIconSm = LoadIcon(NULL , IDI_APPLICATION);
return RegisterClassEx(&wcex);
}
//
// 関数: InitInstance(HINSTANCE, int)
//
// 目的: メイン ウィンドウを作成します。
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hWnd = CreateWindow(TEXT("HP"), TEXT("HP"), WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//
// 関数: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// 目的: メイン ウィンドウのメッセージを処理します。
//
// WM_CREATE - ウインドウ作成時の処理
// WM_SIZE - ウインドウサイズ変更時の処理
// WM_VSCROLL - スクロール時の処理
// WM_COMMAND - アプリケーション メニューの処理
// WM_DESTROY - 中止メッセージを表示して戻る
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
HWND static hEdit;
static int wx; // 画面の幅
static int wy; // 画面の高さ
static int y; // スクロール位置
static int dy; // 増分
static int range; // 最大スクロール範囲
static int yclient; // 現在のクライアント領域の高さ
switch (message)
{
case WM_CREATE:
hEdit = CreateWindowEx(WS_EX_CLIENTEDGE, // 拡張ウィンドウスタイル
TEXT("EDIT"),
TEXT("ここに入力"),
WS_CHILD | WS_VISIBLE | ES_MULTILINE | WS_VSCROLL,
0, 0,
0, 0,
hWnd,
(HMENU)IDC_EDIT1,
hInst,
NULL);
wx = GetSystemMetrics(SM_CXSCREEN);
wy = GetSystemMetrics(SM_CYSCREEN);
break;
case WM_SIZE:
yclient = HIWORD(lParam);
range = wy - yclient;
y = min(y, range);
SetScrollRange(hEdit, SB_VERT, 0, range, FALSE);
SetScrollPos(hEdit, SB_VERT, y, TRUE);
MoveWindow(hEdit, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
break;
case WM_VSCROLL:
switch (LOWORD(wParam))
{
case SB_LINEUP:
dy = -1;
break;
case SB_LINEDOWN:
dy = 1;
break;
case SB_THUMBPOSITION:
dy = HIWORD(wParam) - y;
break;
case SB_PAGEDOWN:
dy = 10;
break;
case SB_PAGEUP:
dy = -10;
break;
default:
dy = 0;
break;
}
dy = max(-y, min(dy, range - y));
if (dy != 0)
{
y += dy;
ScrollWindow(hEdit, 0, -dy, NULL, NULL);
SetScrollPos(hEdit, SB_VERT, y, TRUE);
UpdateWindow(hEdit);
}
break;
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// 選択されたメニューの解析:
switch (wmId)
{
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
上記の太線で示している箇所のみ追加です。
#define IDM_ABOUT 104 #define IDM_EXIT 105 #define IDC_HP 109 #define IDC_EDIT1 1001
#include "Resource.h"
/////////////////////////////////////////////////////////////////////////////
//
// メニュー
//
IDC_HP MENU
BEGIN
POPUP "ファイル(&F)"
BEGIN
MENUITEM "アプリケーションの終了(&X)", IDM_EXIT
END
POPUP "ヘルプ(&H)"
BEGIN
MENUITEM "バージョン情報(&A)...", IDM_ABOUT
END
END