山本ワールド
Windowsプログラミング
アルゴリズム Vitual C++ 2008/2013によるWin32/Win64 APIレベルのプログラム 基礎 Vitual C++ 2008/2013によるAPIレベルのプログラム(32/64bit) Wix3でインストーラーを作る Visual C++ 2008 Standard Editonによるフォームアプリケーションのプログラム(32/64bit) Vitual C++ 2008 Standard EditonによるAPIレベルのプログラム(32/64bit) Windows 7対応 Visual C++ 2008 ExpressによるAPIレベルのプログラム Visual C++ 2005 ExpressによるAPIレベルのプログラム Visual C++ Versiosn 5 BORLAND C++ Windowsプログラム全般 Excel VBA その他MDI(Multiple Document Interface)とステータスバーをサポートしたサンプル
概要
MDI(Multiple Document Interface)は下図の様な1つのアプリケーンの中にドキュメントを表示する複数のウィンドウが存在するインターフェースです。
本プログラムはMDIにステータスバーを追加したサンプルです。
本ページでは、MDI(Multiple Document Interface)サンプル1にステータスバーを付加するための変更点のみ記述しております。
ステータスバーについては、以下のページを参照してください。
ステータスバー
本プログラムはMDIにステータスバーを追加したサンプルです。
本ページでは、MDI(Multiple Document Interface)サンプル1にステータスバーを付加するための変更点のみ記述しております。
ステータスバーについては、以下のページを参照してください。
ステータスバー
テスト環境
コンパイラ
Visual C++ 2008 Standard 32/64bitVisual C++ 2013 Express 32/64bit
プロジェクトの作成
Win32プロジェクト Windowsアプリケーション実行環境
Windows 7 EnterPrise Service Pack 1 64bitWindows 10 Home 32/64bit
プログラムソースの概要
mdi2.cpp
FrameWndProc
フレームウィンドウのプロシージャーです。WM_CREATE
CreateStatusWindow APIによりステータスバーを作成します。ステータスバーにSB_SETPARTSメッセージを送信しステータスバーの分割数と幅を設定します。
WM_SIZE
ステータスバーにWM_SIZEメッセージを送信しステータスバーの大きさと位置を調整します。GetWindowRect APIによりステータスバーのウィンドウサイズを取得します。
WM_SIZEメッセージのLPARAMよりウィンドウサイズを取得しステータスバーの大きさ分を差し引いて MoveWindow APIによりクライアントウィンドウの大きさを変更します。
戻り値はメッセージは処理済みであることを示すため0を返す必要があります。
DocProc
ドキュメントウィンドウのプロシージャーです。WM_MDIACTIVATE
ドキュメントウィンドウがアクティブになった時に呼び出されます。LPARAMにはアクティブになるウィンドウのハンドル、WPARAMには非アクティブになるウィンドウのハンドルが格納されています。
LPARAMと自身のウィンドウハンドルを比較します。比較結果によりステータスバーの文字列を設定します。
同一
アクティブドキュメントウィンドウのテキスト異なる場合
空白にするプログラムソース
MDI(Multiple Document Interface)サンプル1からの変更箇所を着色しています。
mdi2.cpp
// MDI(Multiple Document Interface)とステータスバーをサポートしたサンプル
#include <windows.h>
#include <commctrl.h>
#include <tchar.h>
#include "resource.h"
#pragma comment(lib,"comctl32.lib")
#define IDM_FIRSTCHILD 200 //ドキュメントウィンドウの最初のID番号 以降自動的に1ずつ加算される
#define ID_STATUS 100 // ステータスバーのID
#ifdef _WIN64
typedef LONG_PTR WINDOW_LONG_PTR;
#else
typedef LONG WINDOW_LONG_PTR;
#endif
LRESULT CALLBACK FrameWndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK DocProc(HWND, UINT, WPARAM, LPARAM);
BOOL CALLBACK CloseAllProc(HWND, LPARAM);
int MyRegisterWC(WNDPROC, LPCTSTR, HBRUSH);
TCHAR szFrameClassName[] = _TEXT("mdi_org"); //フレームウィンドウクラス
TCHAR szChildDoc[] = _TEXT("document_org"); //ドキュメント
HMENU hMenuFirst, hMenuDoc;
HMENU hMenuFirstWnd, hMenuDocWnd;
HINSTANCE hInst;
HWND hStatus;
int doc_no=0; // ドキュメント(子ウィンドウ)番号
int WINAPI _tWinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst,
TCHAR* lpsCmdLine, int nCmdShow){
MSG msg;
HWND hFrame, hClient;
::hInst = hCurInst;
// フレームウィンドウのクラスの登録
if(!MyRegisterWC(FrameWndProc, szFrameClassName,(HBRUSH)(COLOR_APPWORKSPACE + 1)))
return FALSE;
// ドキュメントウィンドウのクラスの登録
if(!MyRegisterWC(DocProc, szChildDoc, (HBRUSH)GetStockObject(WHITE_BRUSH)))
return FALSE;
// フレームウィンドウのメニューを読み込む
::hMenuFirst = LoadMenu(hInst, _TEXT("MYMENU"));
::hMenuFirstWnd = GetSubMenu(hMenuFirst, 0);
// ドキュメントウィンドウのメニューを読み込む
::hMenuDoc = LoadMenu(hInst, _TEXT("MYDOCUMENT"));
::hMenuDocWnd = GetSubMenu(hMenuDoc, 1);
// フレームウィンドウの作成
hFrame = CreateWindow(
szFrameClassName,
_TEXT("Multiple Document Interface2"), // ウィンドウタイトル
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
::hMenuFirst,
::hInst,
NULL);
hClient = GetWindow(hFrame, GW_CHILD);
ShowWindow(hFrame, nCmdShow);
UpdateWindow(hFrame);
while (GetMessage(&msg, NULL, 0, 0)) {
if (!TranslateMDISysAccel(hClient, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
DestroyMenu(hMenuDoc);
return int(msg.wParam);
}
// フレームウィンドウのプロシージャー
LRESULT CALLBACK FrameWndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp){
static HWND hClient;
int sb_size[] = { 100, 200, -1 };
HWND hChild;
switch (msg) {
case WM_CREATE:{
hStatus = CreateStatusWindow(WS_CHILD | SBARS_SIZEGRIP | CCS_BOTTOM | WS_VISIBLE, _TEXT(""), hWnd, ID_STATUS);
SendMessage(hStatus, SB_SETPARTS, (WPARAM)3, (LPARAM)(LPINT)sb_size);
// クライアントウィンドウの作成
CLIENTCREATESTRUCT ccs;
ccs.hWindowMenu = hMenuFirstWnd;
ccs.idFirstChild = IDM_FIRSTCHILD;//ドキュメントウィンドウの最初のID番号
hClient = CreateWindow(
_TEXT("MDICLIENT"),
NULL,
WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN,
0, 0, 0, 0,
hWnd,
(HMENU)1,
::hInst,
(LPSTR)&ccs);
return 0;
}
case WM_COMMAND:
switch (LOWORD(wp)) {
case IDM_NEW:{ // 新規作成メニュー選択時 子ウィンドウの作成
MDICREATESTRUCT mdic;
TCHAR str[64];
wsprintf(str, _TEXT("テキスト %d"), ::doc_no);
TCHAR* text=_tcsdup(str);
wsprintf(str, _TEXT("DOCUMENT[%d]"), ::doc_no);
mdic.szClass = szChildDoc;
mdic.szTitle = str;
mdic.hOwner = ::hInst;
mdic.x = CW_USEDEFAULT;
mdic.y = CW_USEDEFAULT;
mdic.cx = CW_USEDEFAULT;
mdic.cy = CW_USEDEFAULT;
mdic.style = 0;
mdic.lParam = (LPARAM)text; //ドキュメントウィンドウ作成時に渡すパラメータ
hChild = (HWND)SendMessage(hClient, WM_MDICREATE, 0,
(LPARAM)&mdic);
++ ::doc_no;
return 0;
}
case IDM_CLOSE: // アクティブなドキュメントウィンドウを閉じる
hChild = (HWND)SendMessage(hClient, WM_MDIGETACTIVE, 0, 0);
if (hChild)
SendMessage(hClient, WM_MDIDESTROY, (WPARAM)hChild, 0);
return 0;
case IDM_EXIT: // プログラムを終了
SendMessage(hWnd, WM_CLOSE, 0, 0);
return 0;
case IDM_CLOSEALL: // 全てのドキュメントウィンドウを閉じる
EnumChildWindows(hClient, &CloseAllProc, 0);
return 0;
case IDM_TILE: // ドキュメントウィンドウを並べて表示
SendMessage(hClient, WM_MDITILE, 0, 0);
return 0;
case IDM_CASCADE: // ドキュメントウィンドウを重ねて表示
SendMessage(hClient, WM_MDICASCADE, 0, 0);
return 0;
case IDM_ARRANGE: // アイコンの整列(最小化されたドキュメントウィンドウのアイコンを整列)
SendMessage(hClient, WM_MDIICONARRANGE, 0, 0);
return 0;
default:
hChild = (HWND)SendMessage(hClient, WM_MDIGETACTIVE, 0, 0);
if (IsWindow(hChild))
SendMessage(hChild, WM_COMMAND, wp, lp);
break;
}
break;
case WM_SIZE:{
int wx,wy,sx,sy;
RECT rc;
SendMessage(hStatus, WM_SIZE, wp, lp);
GetWindowRect(hStatus, &rc);
sx=rc.right-rc.left;
sy=rc.bottom-rc.top;
wx = LOWORD(lp);
wy = HIWORD(lp);
wy-=sy;
MoveWindow(hClient,0,0,wx,wy,TRUE);
return 0;
}
case WM_CLOSE: // フレームウィンドウの終了時に呼び出される。
SendMessage(hWnd, WM_COMMAND, IDM_CLOSEALL, 0);
if (GetWindow(hClient, GW_CHILD))
return 0;
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefFrameProc(hWnd, hClient, msg, wp, lp);
}
// ドキュメントウィンドウのプロシージャー
LRESULT CALLBACK DocProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp){
static HWND hClient, hFrame;
TCHAR* str;
switch (msg) {
case WM_CREATE:{
hClient = GetParent(hWnd);
hFrame = GetParent(hClient);
LPCREATESTRUCT lpcs=(LPCREATESTRUCT)lp;
LPMDICREATESTRUCT lpmdis=(LPMDICREATESTRUCT)lpcs->lpCreateParams;
str=(TCHAR*)lpmdis->lParam; // 子ウィンドウ作成時に指定されたパラメータを取得
// 各ウィンドウごとに個別に使用できるメモリにフレームウィンドウから渡された文字列を保存
SetWindowLongPtr(hWnd, GWLP_USERDATA, (WINDOW_LONG_PTR)str);
return 0;
}
case WM_PAINT:{
PAINTSTRUCT ps;
HDC hdc=BeginPaint(hWnd,&ps);
// 各ウィンドウごとに個別に使用できるメモリから文字列を取得
str=(TCHAR*)GetWindowLongPtr(hWnd, GWLP_USERDATA);
TextOut(hdc,0,0,str,int(_tcslen(str)));
EndPaint(hWnd,&ps);
break;
}
case WM_SIZE:
break;
case WM_MDIACTIVATE:
if (lp == (LPARAM)hWnd){
SendMessage(hClient, WM_MDISETMENU, (WPARAM)::hMenuDoc, (LPARAM)::hMenuDocWnd);
str=(TCHAR*)GetWindowLongPtr(hWnd, GWLP_USERDATA);
SendMessage(hStatus, SB_SETTEXT, (WPARAM)0 | 0, (LPARAM)str);
}else{
SendMessage(hClient, WM_MDISETMENU, (WPARAM)::hMenuFirst, (LPARAM)::hMenuFirstWnd);
SendMessage(hStatus, SB_SETTEXT, (WPARAM)0 | 0, (LPARAM)_TEXT(""));
}
DrawMenuBar(hFrame);
return 0;
}
return (DefMDIChildProc(hWnd, msg, wp, lp));
}
// 指定するMDIドキュメントウィンドウを閉じる(EnumChildWindowsから呼び出される)
BOOL CALLBACK CloseAllProc(HWND hWnd, LPARAM lp){
SendMessage(GetParent(hWnd), WM_MDIDESTROY, (WPARAM)hWnd, 0);
return TRUE;
}
// ウィンドウクラスを登録
int MyRegisterWC(WNDPROC lpfnWndProc, LPCTSTR lpszClassName, HBRUSH hbrBack){
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = lpfnWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInst; //インスタンス
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = hbrBack;
wc.lpszMenuName = NULL; //メニュー名
wc.lpszClassName = lpszClassName;
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
return(RegisterClassEx(&wc));
}
resource.h
#define IDM_NEW 1000
#define IDM_EXIT 1001
#define IDM_CLOSE 1003
#define IDM_CASCADE 1005
#define IDM_TILE 1006
#define IDM_CLOSEALL 1007
#define IDM_ARRANGE 1008
mdi2.rc
#include <windows.h>
#include "resource.h"
MYMENU MENU DISCARDABLE
BEGIN
POPUP "ファイル(&F)"
BEGIN
MENUITEM "新規作成(&N)", IDM_NEW
MENUITEM "終了(&X)", IDM_EXIT
END
END
MYDOCUMENT MENU DISCARDABLE
BEGIN
POPUP "ファイル(&F)"
BEGIN
MENUITEM "新規作成(&N)", IDM_NEW
MENUITEM "閉じる(&C)", IDM_CLOSE
MENUITEM SEPARATOR
MENUITEM "終了(&X)", IDM_EXIT
END
POPUP "ウィンドウ(&W)"
BEGIN
MENUITEM "重ねて表示(&C)", IDM_CASCADE
MENUITEM "並べて表示(&T)", IDM_TILE
MENUITEM "すべて閉じる(&L)", IDM_CLOSEALL
MENUITEM "アイコンの整列(&A)", IDM_ARRANGE
END
END
ソースファイルと実行ファイルのダウンロード
Copyright (C) 2012 山本ワールド All Rights Reserved.