C++GUI按钮卡在底部

C++ GUI button stuck to the bottom

本文关键字:底部 按钮 C++GUI      更新时间:2023-10-16

我正在windows.h中为我妈妈制作一个C++GUI表单,我不知道如何将"adaugare"、"iesire"、"refresh"等按钮粘在windows表单的底部。我想让它们在调整表单大小时自动移动,这样它们就可以始终位于右下方。伙计们,请帮帮我,因为我是C++Gui的初学者!

#if defined(UNICODE) && !defined(_UNICODE)
#define _UNICODE
#elif defined(_UNICODE) && !defined(UNICODE)
#define UNICODE
#endif
#include <tchar.h>
#include <windows.h>
#include <iostream>
#include <string>
#include <cstring>
#include <fstream>
using namespace std;
ofstream fout;
ifstream fin;
/*  Declare Windows procedure  */
LRESULT CALLBACK WindowProcedure(HWND, UINT, WPARAM, LPARAM);
HWND hwnd;               /* This is the handle for our window */
HWND button[5];
HWND banda[100];
HWND tip[100];
HWND lungime[100];
HWND latime[100];
HWND data1[100];
HWND button_valideaza[100];
int button_index[100];
int i = 0, counter = 1;
char buffer[10];
char textEP[20];
char textTip[20];
char textLungime[20];
char textLatime[20];
char textData[20];
char textAll[101];


/*  Make the class name into a global variable  */
TCHAR szClassName[] = _T("CodeBlocksWindowsApp");

int getIndex(){
fin.open("record.txt", std::ios_base::in);
string line1;
string line;
while(getline(fin, line1)) {
line = line1;
}
char save[line.size()];
strcpy(save, line.c_str());
char *p = strtok(save, " ");
fin.close();
return atoi(p);
}
void refresh() {
}

int WINAPI WinMain(HINSTANCE hThisInstance,
HINSTANCE hPrevInstance,
LPSTR lpszArgument,
int nCmdShow)
{
MSG messages;            /* Here messages to the application are saved */
WNDCLASSEX wincl;        /* Data structure for the windowclass */
/* The Window structure */
wincl.hInstance = hThisInstance;
wincl.lpszClassName = szClassName;
wincl.lpfnWndProc = WindowProcedure;      /* This function is called by windows */
wincl.style = CS_DBLCLKS;                 /* Catch double-clicks */
wincl.cbSize = sizeof(WNDCLASSEX);
/* Use default icon and mouse-pointer */
wincl.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wincl.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
wincl.hCursor = LoadCursor(NULL, IDC_ARROW);
wincl.lpszMenuName = NULL;                 /* No menu */
wincl.cbClsExtra = 0;                      /* No extra bytes after the window class */
wincl.cbWndExtra = 0;                      /* structure or the window instance */
/* Use Windows's default colour as the background of the window */
wincl.hbrBackground = (HBRUSH)COLOR_BACKGROUND;
/* Register the window class, and if it fails quit the program */
if (!RegisterClassEx(&wincl))
return 0;
/* The class is registered, let's create the program*/
hwnd = CreateWindowEx(
0,                   /* Extended possibilites for variation */
szClassName,         /* Classname */
_T("Flux Artego"),       /* Title Text */
WS_OVERLAPPEDWINDOW, /* default window */
CW_USEDEFAULT,       /* Windows decides the position */
CW_USEDEFAULT,       /* where the window ends up on the screen */
700,                 /* The programs width */
300,                 /* and height in pixels */
HWND_DESKTOP,        /* The window is a child-window to desktop */
NULL,                /* No menu */
hThisInstance,       /* Program Instance handler */
NULL                 /* No Window Creation data */
);
/* Make the window visible on the screen */
ShowWindow(hwnd, nCmdShow);
/* Run the message loop. It will run until GetMessage() returns 0 */
while (GetMessage(&messages, NULL, 0, 0))
{
/* Translate virtual-key messages into character messages */
TranslateMessage(&messages);
/* Send message to WindowProcedure */
DispatchMessage(&messages);
}
/* The program return-value is 0 - The value that PostQuitMessage() gave */
return messages.wParam;
}

/*  This function is called by the Windows function DispatchMessage()  */
void scrie() {
}
LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
WORD cmd = LOWORD(wParam);
switch (message)                  /* handle the messages */
{
case WM_CREATE:   // fac butoane, label etc
counter = getIndex();
counter++;
fout.open("record.txt", std::ios_base::app);
std::fill_n(button_index, 100, -1);
button[0] = CreateWindow("BUTTON",
"Iesire",
WS_VISIBLE | WS_CHILD | WS_BORDER,
560, 220, 100, 20,
hwnd, (HMENU)1, NULL, NULL);   // (HMENU) 1 reprezinta care case din switch se executa
button[1] = CreateWindow("BUTTON",
"Adauga",
WS_VISIBLE | WS_CHILD | WS_BORDER,
450, 220, 100, 20,
hwnd, (HMENU)2, NULL, NULL);
button[2] = CreateWindow("BUTTON",
"Refresh",
WS_VISIBLE | WS_CHILD | WS_BORDER,
340, 220, 100, 20,
hwnd, (HMENU)3, NULL, NULL);

break;
case WM_COMMAND:  // fac instructiuni butoane
switch (cmd)
{
case 1:
//::MessageBeep(MB_ICONERROR);
//::MessageBox(hwnd, "Ai salvat ?", "atentie", MB_OKCANCEL);
cout << "GoodBye!";
PostQuitMessage(0);
break;
case 2:   // Adaug nou record
banda[i] = CreateWindow("EDIT",
"EP",
WS_BORDER | WS_CHILD | WS_VISIBLE,
20, 30 * i, 30, 25,
hwnd, NULL, NULL, NULL);
tip[i] = CreateWindow("EDIT",
"100",
WS_BORDER | WS_CHILD | WS_VISIBLE,
55, 30 * i, 100, 25,
hwnd, NULL, NULL, NULL);
lungime[i] = CreateWindow("EDIT",
"Lungime",
WS_BORDER | WS_CHILD | WS_VISIBLE,
160, 30 * i, 100, 25,
hwnd, NULL, NULL, NULL);
latime[i] = CreateWindow("EDIT",
"Latime",
WS_BORDER | WS_CHILD | WS_VISIBLE,
265, 30 * i, 100, 25,
hwnd, NULL, NULL, NULL);
data1[i] = CreateWindow("EDIT",
"Data",
WS_BORDER | WS_CHILD | WS_VISIBLE,
370, 30 * i, 100, 25,
hwnd, NULL, NULL, NULL);
button_valideaza[i] = CreateWindow("BUTTON",
"Scrie",
WS_VISIBLE | WS_CHILD | WS_BORDER,
475, 30 * i, 80, 20,
hwnd, (HMENU)(i+5), NULL, NULL);
i++;
break;
case 3:         // Refresh
refresh();
break;
case 4:         // Compute
break;
default:
if (cmd > 4 && cmd < 103)
{
int index;
if (button_index[cmd-3] == -1){   // daca buton index nu a fost setata
button_index[cmd-3] = counter;
index = counter;
//cout << "Prima apasare a butinului " << cmd-3 << " si primeste index "<<counter<<endl;
counter++;
} else {                       // a fost setat
index = button_index[cmd-3];
//cout << "Deja apasat butonul "<< cmd-3 << " si are vechiul index " << button_index[cmd-3] << endl;
::MessageBox(hwnd, "Pentru a rescrie apasa pe REFRESH","Suprascriere", MB_OK);
}
int gwtstat = 0;
gwtstat = GetWindowText(banda[cmd-5], &textEP[0], 20);
gwtstat = 0;
gwtstat = GetWindowText(tip[cmd-5], &textTip[0], 20);
gwtstat = 0;
gwtstat = GetWindowText(lungime[cmd-5], &textLungime[0], 20);
gwtstat = 0;
gwtstat = GetWindowText(latime[cmd-5], &textLatime[0], 20);
gwtstat = 0;
gwtstat = GetWindowText(data1[cmd-5], &textData[0], 20);
itoa(index, buffer, 10);
strcpy(textAll, buffer);
strcat(textAll," ");
strcat(textAll,textEP);
strcat(textAll, " ");
strcat(textAll,textTip);
strcat(textAll, " ");
strcat(textAll, textLungime);
strcat(textAll, " ");
strcat(textAll, textLatime);
strcat(textAll, " ");
strcat(textAll, textData);
fout << textAll << "n";
::MessageBox(hwnd, textAll,"text", MB_OKCANCEL);
}
break;
}
break;
case WM_DESTROY:
fout.close();
PostQuitMessage(0);       /* send a WM_QUIT to the message queue */
break;
default:                      /* for messages that we don't deal with */
return DefWindowProc(hwnd, message, wParam, lParam);
}

return 0;
}

不幸的是,没有自动执行此操作的机制。您必须编写代码来侦听大小调整事件,计算每个控件的适当大小和位置,并相应地移动它。一旦你了解了这个过程,它就相对简单了,但也相当乏味,尤其是当你有大量的控件需要调整时。

首先,将WM_SIZE消息的处理程序添加到主窗口的窗口过程中。调整窗口大小时会发送此消息。

在该处理程序中,您将调用MoveWindowSetWindowPos函数来更改子窗口(即控件;即按钮)的位置。

以下是一些示例代码:

case WM_SIZE:
{
const int cxPadding = 12;
const int cyPadding = 12;
// Get client rectangle for parent window.
RECT rcParent;
GetClientRect(hwnd, &rcParent);
RECT rcButton[5];
// Adjust the position of the first button.
// It will be the furthest one to the right.
GetClientRect(button[0], &rcButton[0]);
SetWindowPos(button[0],
NULL,
(rcParent.right  - cxPadding - (rcButton[0].right  - rcButton[0].left)),
(rcParent.bottom - cyPadding - (rcButton[0].bottom - rcButton[0].top)),
0,
0,
SWP_NOACTIVATE | SWP_NOREPOSITION | SWP_NOSIZE | SWP_NOZORDER);
// Adjust the position of the second button.
// It will be the next to the first one.
GetClientRect(button[1], &rcButton[1]);
SetWindowPos(button[1],
NULL,
(rcParent.right  - cxPadding - (rcButton[0].right  - rcButton[0].left)
- cxPadding - (rcButton[1].right  - rcButton[1].left)),
(rcParent.bottom - cyPadding - (rcButton[1].bottom - rcButton[1].top)),
0,
0,
SWP_NOACTIVATE | SWP_NOREPOSITION | SWP_NOSIZE | SWP_NOZORDER);
// etc.
}

要在重新定位大量子控件时减少闪烁,可以使用DeferWindowPos函数。这要求您在开始时调用BeginDeferWindowPos,然后为每个控件调用DeferWindowPos(就像SetWindowPos一样),最后在调整完所有控件后调用EndDeferWindowPos。请参阅DeferWindowPos的意义何在?在陈的博客上。

此外,如果您正在尝试学习Windows API编程,请帮自己一个忙,并购买Charles Petzold的经典书籍《编程Windows(第5版)》。是的,你需要第五版。较新的版本涵盖了不同的编程语言/框架。你可以在亚马逊上找到用过的副本。