MDIでステータスバー等の領域を残すには

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
トム

MDIでステータスバー等の領域を残すには

#1

投稿記事 by トム » 14年前

図のようにCHILDウィンドウを最大化すると
ステータスバーやツールバーの領域まで拡大
されてしまって困っています。
この問題はどのように解決すればいいのでしょうか。

よろしくお願いします。



以下コードです

#include <windows.h>
#include "resource.h"
#include <CommCtrl.h>

LRESULT CALLBACK FrameProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK ChildProc(HWND, UINT, WPARAM, LPARAM);
char szClassNme[/url] = "ウィンドウクラス・ネーム";
HWND hwCl;
HWND hwFm;
HINSTANCE hInstFm;
HMENU hmFm;
HWND hwSb;

void myError(LPCSTR msg){MessageBox(NULL,msg,"",0);}

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPreInst,
LPSTR lpszCmdLine, int nCmdShow)
{
hInstFm=hInst;
MSG msg;
WNDCLASS wc;

if (!hPreInst) {
wc.style =CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc =FrameProc;
wc.cbClsExtra =0;
wc.cbWndExtra =0;
wc.hInstance =hInst;
wc.hIcon =NULL;
wc.hCursor =LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground =(HBRUSH)(COLOR_APPWORKSPACE+1);
wc.lpszMenuName =NULL;
wc.lpszClassName =szClassNme;
if (!RegisterClass(&wc)){
myError("1");
return FALSE;
}
}
hmFm=LoadMenu(hInst,MAKEINTRESOURCE(IDR_MENU1));
hwFm = CreateWindow(szClassNme,"FRAME",
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
NULL,hmFm,hInst,NULL);

wc.lpszClassName="CCN";
wc.lpfnWndProc=ChildProc;
wc.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);

if (!RegisterClass(&wc)){
myError("1");
return FALSE;
}
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (msg.wParam);
}

LRESULT CALLBACK FrameProc(HWND hw, UINT msg, WPARAM wp, LPARAM lp)
{
switch (msg) {
case WM_CREATE:
//Create Client
CLIENTCREATESTRUCT ccs;
ccs.hWindowMenu=GetSubMenu(hmFm,1);
ccs.idFirstChild=1;
hwCl= CreateWindow( "MDICLIENT",NULL,
WS_CHILD | WS_CLIPCHILDREN | WS_VSCROLL | WS_HSCROLL | WS_VISIBLE,
0, 0, 0, 0, hw, (HMENU)1, hInstFm, (LPSTR) &ccs);

//Create Statusbar
InitCommonControls();
hwSb=CreateWindowEx(0,STATUSCLASSNAME,NULL,
WS_CHILD | SBARS_SIZEGRIP | CCS_BOTTOM | WS_VISIBLE,
0,0,0,0,hw,(HMENU)2,hInstFm,NULL);
break;
case WM_COMMAND:
switch(wp){
case IDM_NEW1:
HWND hwCh;
MDICREATESTRUCT mcs;
mcs.x=CW_USEDEFAULT;
mcs.y=CW_USEDEFAULT;
mcs.cx=CW_USEDEFAULT;
mcs.cy=CW_USEDEFAULT;
mcs.szClass="CCN";
mcs.szTitle="child";
mcs.hOwner=hInstFm;
mcs.SSS=WS_CHILD;//SSS→style
mcs.lParam=0;
hwCh=(HWND)SendMessage(hwCl,WM_MDICREATE,0,(LPARAM)&mcs);
break;
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefFrameProc(hw, hwCl,msg, wp, lp);
}

LRESULT CALLBACK ChildProc(HWND hw, UINT msg, WPARAM wp, LPARAM lp){
return DefMDIChildProc(hw,msg,wp, lp);
}

ISLe

Re:MDIでステータスバー等の領域を残すには

#2

投稿記事 by ISLe » 14年前

ChildProc関数でWM_GETMINMAXINFOを処理してください。
switch (msg) {
    case WM_GETMINMAXINFO:
        MINMAXINFO *pi = (MINMAXINFO*)lp;
        pi->ptMaxPosition.x = (最大化時の左上X座標);
        pi->ptMaxPosition.y = (最大化時の左上Y座標);
        pi->ptMaxSize.x = (最大化時の幅);
        pi->ptMaxSize.y = (最大化時の高さ);
        return 0;
    }

トム

Re:MDIでステータスバー等の領域を残すには

#3

投稿記事 by トム » 14年前

ありがとうございます。
そんなデータをセットするメッセージがあったんですね。

しかし相変わらずウィンドウを動かした時等には画像のように
ステータスバー領域が侵略されてしまいます・・・。

この問題を解決する方法もご存知でしょうか?
よろしくお願いいたします。

たろ

Re:MDIでステータスバー等の領域を残すには

#4

投稿記事 by たろ » 14年前

私もWin32APIでMDI+ステータスバーのアプリを作りましたが、そんな現象に出くわしたことはなく、
WM_GETMINMAXINFOメッセージも知らなかったので、不思議に思っていろいろ試してみたところ、

・MDIクライアントがステータスバーの上にかぶってしまっている

ことが原因と思われます。

WinXPで試しましたが、以下でどうでしょうか。

(1)MDIクライアントとステータスバーを作る順番を逆にする。
   ※先にステータスバーを作った後、MDIクライアントを作る。

(2)MDIクライアントのウィンドウスタイルに WS_CLIPSIBLINGS を追加する。
   ※兄弟ウィンドウ(ステータスバー)の領域を侵食しない。

追記訂正:
「MDIクライアントがステータスバーの上にかぶって」という表現は正しくないような・・
「MDIクライアントがステータスバーの領域にまで広がってしまっている」が適切かな・・ 画像

トム

Re:MDIでステータスバー等の領域を残すには

#5

投稿記事 by トム » 14年前

無事できました。ありがとうございます!

WS_CLIPSIBLINGSなんてものがあったんですね。目から鱗です。
まだまだ初心者なものでwindow stylesのことなんて
全然わからずに数時間(十数時間?)彷徨っていました。

ISLeさん、たろさん、本当にありがとうございました。

ISLe

Re:MDIでステータスバー等の領域を残すには

#6

投稿記事 by ISLe » 14年前

フレームウインドウのリサイズに対応できていないのではないでしょうか。
case WM_SIZE:
        {
            RECT rc;
            SendMessage(hwSb, WM_SIZE, wp, lp);
            GetWindowRect(hwSb, &rc);
            MoveWindow(hwCl,0,0,LOWORD(lp),HIWORD(lp)-(rc.bottom-rc.top),TRUE);
        }
        return 0; // 必須!!
FrameProc関数のメッセージ処理に上記のコードを追加してみてください。

#WM_GETMINMAXINFOは見当違いでした。すみません。

トム

Re:MDIでステータスバー等の領域を残すには

#7

投稿記事 by トム » 14年前

ISLeさん

ありがとうございます。
どうやらそちらの方法の方が優れていそうですね。
チャイルドウィンドウが動くときにもWM_SIZEメッセージは送られるんですね。
まだまだ細かい理屈はわかりませんが

大変勉強になりました。これからもっと精進します。ありがとうございます。

閉鎖

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