我有一个Win32 C ++ MDI表单,顶部是一个工具栏,底部是一个状态栏,状态栏上是一个编辑控件,其余的工作区都为子窗口清除。
以下是创建编辑控件的代码:
HFONT hfDefault;
HWND hEdit;
TCHAR lpszSometext[] = L"This is the first line in this edit control "
L"This is the second line in this edit control "
L"This is the third line in this edit control ";
hEdit = CreateWindowEx(
WS_EX_CLIENTEDGE, L"EDIT",
NULL,
WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL | ES_LEFT | ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL,
0, 0, 0, 0,
hWnd,
(HMENU)IDC_MAIN_EDIT,
GetModuleHandle(NULL),
NULL);
if (hEdit == NULL)
MessageBox(hWnd, L"Could not create edit control.", L"Error", MB_OK | MB_ICONERROR);
SendMessage(hEdit, WM_SETTEXT, 0, (LPARAM)lpszSometext);
hfDefault = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
SendMessage(hEdit, WM_SETFONT, (WPARAM)hfDefault, MAKELPARAM(FALSE, 0));
这是在主窗口回调的WM_SIZE中调整工具栏,状态栏和编辑控件大小的代码;
HWND hToolbar, hStatusbar, hEdit, hMDI;
RECT rcToolbar, rcStatusbar, rcClient;
int iToolbarHeight, iStatusbarHeight, iEditHeight, iMDIHeight;
iEditHeight = 60;
hToolbar = GetDlgItem(hWnd, IDC_MAIN_TOOL);
SendMessage(hToolbar, TB_AUTOSIZE, 0, 0);
hStatusbar = GetDlgItem(hWnd, IDC_MAIN_STATUS);
SendMessage(hStatusbar, WM_SIZE, 0, 0);
GetWindowRect(hToolbar, &rcToolbar);
iToolbarHeight = rcToolbar.bottom - rcToolbar.top;
GetWindowRect(hStatusbar, &rcStatusbar);
iStatusbarHeight = rcStatusbar.bottom - rcStatusbar.top;
GetClientRect(hWnd, &rcClient);
iMDIHeight = rcClient.bottom - iToolbarHeight - iStatusbarHeight - iEditHeight;
hEdit = GetDlgItem(hWnd, IDC_MAIN_EDIT);
SetWindowPos(hEdit, NULL, 0, rcClient.bottom - iStatusbarHeight - iEditHeight, rcClient.right, rcClient.bottom - iStatusbarHeight, SWP_NOZORDER);
hMDI = GetDlgItem(hWnd, IDC_MAIN_MDI);
SetWindowPos(hMDI, NULL, 0, iToolbarHeight, rcClient.right, iMDIHeight, SWP_NOZORDER);
所有三个控件的创建方式都与CreateWindowEx()相同,但是在创建时放在编辑控件中的文本是不显示的,并且每当调整主窗体的大小时,编辑控件都会在MDI clint窗口上产生可怕的假象,就像编辑控件试图捕捉到工具栏底部一样。
答案 0 :(得分:0)
这是一个演示@A。马尔基引用链接:MDI child window and status bar C win32 API [closed]
我正在尝试将您的代码与演示结合起来,并重现您的问题。
但是您不需要在我尝试过的代码中描述的问题,但是您可以参考此演示来查找代码中的问题。
ep:
#include <windows.h>
#include <commctrl.h> //per SBARS_SIZEGRIP e STATUSCLASSNAME
#define IDM_OPEN 100
#define IDM_EXIT 101
#define IDM_ABOUT 102
#define IDC_STATUSBAR 103
#define IDM_ARRANGE 104
#define IDM_CASCADE 105
#define IDM_TILE 106
#define IDM_CLOSEALL 107
#define IDM_CLOSE 108
#define ID_CLIENTWND 109
#define IDM_FIRSTCHILD 5000
#define IDC_MAIN_EDIT 133
#define IDC_MAIN_TOOL 134
TCHAR lpszSometext[] = "This is the first line in this edit control "
"This is the second line in this edit control "
"This is the third line in this edit control ";
const char frameClass[] = "myFrameClass";
const char clientClass[] = "mdiclient"; //funziona solo con "mdiclient"
const char childClass[] = "myChildClass";
HWND hWndStatusBar = NULL;
HWND hWndClient = NULL;
HFONT hfDefault;
HWND hEdit;
HWND hToolbar;
//STEP 5 Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_CREATE:
{
//STEP 6: Create Status Bar
hWndStatusBar = CreateWindowEx(0, STATUSCLASSNAME, NULL,
WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP,
0, 0, 0, 0,
hwnd,
(HMENU)IDC_STATUSBAR,
(HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE), NULL);
if (!hWndStatusBar) {
MessageBox(NULL, "Failed To Create The Status Bar", "Error", MB_OK | MB_ICONERROR);
return 0;
}
// Establish the number of partitions or 'parts' the status bar will
// have, their actual dimensions will be set in the parent window's
// WM_SIZE handler.
RECT rc;
GetClientRect(hwnd, &rc);
int nHalf = rc.right / 2;
int nParts[4] = { nHalf, nHalf + nHalf / 3, nHalf + nHalf * 2 / 3, -1 };
SendMessage(hWndStatusBar, SB_SETPARTS, 4, (LPARAM)&nParts);
//crea la finestra CLIENT
CLIENTCREATESTRUCT ccs;
// Assign the 'Window' menu.
ccs.hWindowMenu = GetSubMenu(GetMenu(hwnd), 1); // uno perchè così la finestra appare nel secondo menu (partendo da zero) ovvero nel menu 'Windows'
ccs.idFirstChild = IDM_FIRSTCHILD;
// Create the client window. (quella che contiene i child!!)
hWndClient = CreateWindowEx(WS_EX_CLIENTEDGE, clientClass,//FUNZIONA SOLO CON "mdiclient"
NULL,
WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE,
0, 0, 0, 0,
hwnd, (HMENU)ID_CLIENTWND/*GetMenu(hwnd)*/, GetModuleHandle(NULL), &ccs);
if (hWndClient == NULL) {
MessageBox(NULL, "Client Window Creation Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK);
return 0;
}
break;
}
case WM_SIZE:
{
HWND hToolbar, hEdit, hMDI;
RECT rcToolbar, rcClient;
int iToolbarHeight, iEditHeight, iMDIHeight;
iEditHeight = 60;
hToolbar = GetDlgItem(hwnd, IDC_MAIN_TOOL);
SendMessage(hToolbar, TB_AUTOSIZE, 0, 0);
GetWindowRect(hToolbar, &rcToolbar);
iToolbarHeight = rcToolbar.bottom - rcToolbar.top;
GetClientRect(hwnd, &rcClient);
iMDIHeight = rcClient.bottom - iToolbarHeight - iEditHeight;
//resize the parts
RECT rc;
GetClientRect(hwnd, &rc);
int nHalf = rc.right / 2;
int nParts[4] = { nHalf, nHalf + nHalf / 3, nHalf + nHalf * 2 / 3, -1 };
SendMessage(hWndStatusBar, SB_SETPARTS, 4, (LPARAM)&nParts);
//resize MDI
// get client area of frame window
RECT clientRect;
GetClientRect(hwnd, &clientRect);
int frame_dx = clientRect.right - clientRect.left;
int frame_dy = clientRect.bottom - clientRect.top;
// get client area of status bar
RECT statusRect;
GetClientRect(hWndStatusBar, &statusRect);
int status_dy = statusRect.bottom - statusRect.top;
// position the MDIClient such that it doesn't overlap with status bar
MoveWindow(hWndClient, 0, 0, frame_dx, frame_dy - status_dy, TRUE);
//resize the statusbar
SendMessage(GetDlgItem(hwnd, IDC_STATUSBAR), WM_SIZE, 0, 0);
hEdit = GetDlgItem(hwnd, IDC_MAIN_EDIT);
SetWindowPos(hEdit, NULL, 0, rcClient.bottom - iEditHeight, rcClient.right, rcClient.bottom, SWP_NOZORDER);
hMDI = GetDlgItem(hwnd, ID_CLIENTWND);
SetWindowPos(hMDI, NULL, 0, iToolbarHeight, rcClient.right, iMDIHeight, SWP_NOZORDER);
return 0; //ritorna zero altrimenti la Frame Window ridisegna il MDI client spalmandolo su tutta la client area andando sopra alla status bar
}
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_COMMAND:
if (LOWORD(wParam) == IDM_EXIT) DestroyWindow(hwnd);
if (LOWORD(wParam) == IDM_ABOUT) MessageBox(hwnd, "ABOUT premuto", "ciao", MB_OK);
if (LOWORD(wParam) == IDM_OPEN) {
//apre il file...
MDICREATESTRUCT mdicreate = { 0 };
mdicreate.szClass = childClass;
mdicreate.szTitle = "class_mdichild";
mdicreate.hOwner = (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE); // <- hinstance
mdicreate.x = CW_USEDEFAULT;
mdicreate.y = CW_USEDEFAULT;
mdicreate.cx = CW_USEDEFAULT;
mdicreate.cy = CW_USEDEFAULT;
mdicreate.style = 0;
mdicreate.lParam = 0;
HWND hwndChild = (HWND)SendMessage(hWndClient, WM_MDICREATE, 0, (LPARAM)(LPMDICREATESTRUCT)&mdicreate);
if (hwndChild == NULL) {
MessageBox(hwnd, "Impossibile creare la finestra Child", "Errore", MB_ICONERROR);
}
}
break;
default:
//return DefWindowProc(hwnd,msg,wParam,lParam);
return DefFrameProc(hwnd, hWndClient, msg, wParam, lParam); //per tenere conto delle finestre figlie
}
return DefFrameProc(hwnd, hWndClient, msg, wParam, lParam);
}
LRESULT CALLBACK ChildWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg) {
case WM_COMMAND:
break;
/* All other messages (a lot of them) are processed using default procedures */
default:
return DefMDIChildProc(hwnd, msg, wParam, lParam);
}
return DefMDIChildProc(hwnd, msg, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc;
HWND hwnd;
MSG msg;
//STEP 1: Registering Frame Class Window
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE + 1);//(COLOR_WINDOW);
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
wc.lpszMenuName = NULL;
wc.lpszClassName = frameClass;
if (!RegisterClassEx(&wc)) {
MessageBox(NULL, "Frame Window Registration Failed!", "Error!", MB_ICONEXCLAMATION);
return 0;
}
//la classe CLIENT non la devo registrare?
//STEP 1.2: Registering Child Class Window
wc.lpfnWndProc = (WNDPROC)ChildWndProc;
wc.hIcon = (HICON)LoadImage(0, IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_SHARED);
wc.hIconSm = (HICON)LoadImage(hInstance, childClass, IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
wc.hCursor = (HCURSOR)LoadImage(0, IDC_ARROW, IMAGE_CURSOR, 0, 0, LR_SHARED);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);//(COLOR_WINDOW);
wc.lpszMenuName = NULL;
wc.lpszClassName = childClass;
if (!RegisterClassEx(&wc)) {
MessageBox(NULL, "Child Window Registration Failed!", "Error!", MB_ICONEXCLAMATION);
return 0;
}
//STEP 2: Creating the Window
hwnd = CreateWindowEx(WS_EX_CLIENTEDGE,
frameClass,
"FrameWindow",
WS_VISIBLE | WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
NULL, NULL, hInstance, NULL);
hEdit = CreateWindowEx(
WS_EX_CLIENTEDGE, "EDIT",
NULL,
WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL | ES_LEFT | ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL,
0, 0, 0, 0,
hwnd,
(HMENU)IDC_MAIN_EDIT,
GetModuleHandle(NULL),
NULL);
if (hEdit == NULL)
MessageBox(hwnd, "Could not create edit control.", "Error", MB_OK | MB_ICONERROR);
SendMessage(hEdit, WM_SETTEXT, 0, (LPARAM)lpszSometext);
hfDefault = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
SendMessage(hEdit, WM_SETFONT, (WPARAM)hfDefault, MAKELPARAM(FALSE, 0));
hToolbar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL,
WS_CHILD | TBSTYLE_WRAPABLE, 0, 0, 0, 0,
hwnd, (HMENU)IDC_MAIN_TOOL, GetModuleHandle(NULL), NULL);
if (hToolbar == NULL)
return NULL;
if (hwnd == NULL) {
MessageBox(NULL, "Frame Window Creation Failed!", "Error!", MB_ICONEXCLAMATION);
return 0;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
//STEP 3: Create Menu
HMENU hMenu = CreateMenu(); //crea un menu vuoto
HMENU hSubMenu; //variabile usata per aggiungere sottomenu ti tipo POPUP
hSubMenu = CreatePopupMenu();
AppendMenu(hSubMenu, MF_STRING, IDM_OPEN, "&Open");
AppendMenu(hSubMenu, MF_STRING, IDM_CLOSE, "&Close");
AppendMenu(hSubMenu, MF_SEPARATOR, 0, NULL);
AppendMenu(hSubMenu, MF_STRING, IDM_EXIT, "&Exit");
AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu, "&File"); //aggiunge il sottomenu al menu
hSubMenu = CreatePopupMenu();
AppendMenu(hSubMenu, MF_STRING, IDM_ARRANGE, "Arrange");
AppendMenu(hSubMenu, MF_STRING, IDM_CASCADE, "Cascade");
AppendMenu(hSubMenu, MF_STRING, IDM_TILE, "Tile");
AppendMenu(hSubMenu, MF_STRING, IDM_CLOSEALL, "Close All");
AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu, "&Windows");
hSubMenu = CreatePopupMenu();
AppendMenu(hSubMenu, MF_STRING, IDM_ABOUT, "&About");
AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu, "&Help");
if (hMenu == NULL) {
MessageBox(NULL, "Menu Creation Failed!", "Error!", MB_ICONEXCLAMATION);
return 0;
}
SetMenu(hwnd, hMenu); //setta il menu sulla finestra
//STEP 4: Message Loop
while (GetMessage(&msg, NULL, 0, 0) > 0) {
if (hWndClient && TranslateMDISysAccel(hWndClient, &msg)) continue; //process the predefined MDI specific accelerator keys
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
如果有任何疑问,请随时与我联系。我很乐意帮助您解决问题。