Witam, szukałem wiele na ten temat i nie znalazłem odpowiedzi więc pytam tu. Czy jest jakaś możliwość modyfikacji rozmiaru i rozmieszczenia przycisków "ok", "anuluj" itp w MessageBox'ie ? Wiem że można wybrać rodzaj przycisku, ustawiać flagi itp ale chciałbym zmienić rozmiar przycisków. Czy ktoś wie jak coś takiego zrobić? Z góry dziękuję za pomoc.

- Rejestracja:prawie 19 lat
- Ostatnio:13 dni
- Postów:819
Może ten artykuł jakoś cię naprowadzi...
Rev napisał(a):
Najlepiej będzie w takim przypadku stworzyć własne okno.
Bieluus napisał(a):
No rozumiem, też o tym czytałem lecz to spowoduje iż będę musiał przerobić inne części programu.
Niekoniecznie. Możesz przecież zdefiniować własną funkcję MessageBox o parametrach identycznych, jak oryginalna. Inne części programu nawet nie zauważą zmiany.

- Rejestracja:ponad 21 lat
- Ostatnio:około 11 godzin
Nie można zmieniać rozmiaru przycisków wyświetlanych przez MessageBox()
.
Ale od Visty w górę jest bardzo fajne okienko zwane "task dialog":
#pragma comment(linker,"\"/manifestdependency:type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
#include <Windows.h>
#include <CommCtrl.h>
int main()
{
TASKDIALOGCONFIG tdc = {0};
tdc.cbSize = sizeof(tdc);
tdc.hwndParent = GetConsoleWindow();
tdc.hInstance = GetModuleHandle(NULL);
tdc.dwFlags = TDF_SIZE_TO_CONTENT | TDF_USE_COMMAND_LINKS;
tdc.dwCommonButtons = TDCBF_OK_BUTTON | TDCBF_CANCEL_BUTTON;
tdc.pszWindowTitle = L"Pytanie";
tdc.pszMainIcon = TD_INFORMATION_ICON;
tdc.pszMainInstruction = L"Lorem ipsum";
tdc.pszContent = L"dolor sit amet";
tdc.cButtons = 3;
TASKDIALOG_BUTTON przyciski[] =
{
{100,L"Chcę to"},
{101, L"Chcę tamto"},
{102, L"Nie wiem czego chcę"}
};
tdc.pButtons = przyciski;
// dużo innych pól do zabawy, patrz dokumentacja
int result;
TaskDialogIndirect(&tdc, &result, NULL, NULL);
}

- Rejestracja:około 17 lat
- Ostatnio:około 3 lata
- Lokalizacja:Szczecin
- Postów:4191
O ile dobrze zrozumiałem chodzi Tobie o coś takiego jak poniżej. Kod znalazłem kiedyś na google i dostosowałem nieco do swoich potrzeb. Może są inne metody, ale ta jest skuteczna. Fragmenty kodu pochodzą z mojej aplikacji pisanej wyłacznie w WinAPI. Zmienna MainDialogHandle
to uchwyt głownego okna aplikacji. Pod VCL powinieneś zastapić to za pewne AktywnaFormatka.Handle
lub Appliaction.Handle
. Natomiast zmiennej ActiveWindowHandle
użyłem w kodzie po to gdyż mam poza oknem głownym jeszcze dodatkowe okienko dialogowe. Jeżeli chodzi o funkcję obsługi komunikatów to możesz ją przypisać do okna formatki, tak jak przypisuje ją ja dla okienka MessageBox
, co widać w kodzie poniżej. Oczywiście kod podmienia etykiety przycisków aby zawsze były po angielsku, tak jak GUI całego mojego programu. Ale mając uchwyt okna dialogowego nie problem już zmieniać jego rozmiary czy rozmieszczenie elementów, posiłkując się innym funkcjami WinAPI opisanymi na MSDNie. Co do obsługi klawisza Escape w modyfikowanym dialogu to musiałem go obsłuzyć w taki sposób, bo inaczej okienko w porównaniu do standardowego mi nie reagowało.
//...
const
WM_CHANGEMSGBOX = WM_USER + 2012;
//...
var
PNewMsgBoxProc, POldMsgBoxProc : Pointer;
//...
function MsgBoxProc(AHWnd : HWND; Msg : UINT; AWParam : WParam; ALParam : LParam) : LResult; stdcall;
var
EscapePressed : boolean;
begin
EscapePressed := GetAsyncKeyState(VK_ESCAPE) shr ((SizeOf(SHORT) * 8) - 1) <> 0;
if EscapePressed then
begin
EndDialog(AHWnd, 0);
end;
Result := CallWindowProc(POldMsgBoxProc, AHwnd, Msg, AWParam, ALParam);
end;
function MsgBox(AHWnd : HWND; Text, Title : string; UType : UINT) : integer;
begin
PostMessage(MainDialogHandle, WM_CHANGEMSGBOX, 0, 0);
Result := MessageBox(AHWnd, PChar(Text), PChar(Title), UType);
end;
function MainDlgProc(AHWnd : HWND; Msg : UINT; AWParam : WParam; ALParam : LParam) : BOOL; stdcall;
begin
Result := False;
if Msg = WM_CHANGEMSGBOX then
begin
H := FindWindow(WC_DIALOG, nil);
if GetParent(H) = ActiveWindowHandle then
begin
PNewMsgBoxProc := @MsgBoxProc;
POldMsgBoxProc := Pointer(SetWindowLong(H, GWL_WNDPROC, Integer(PNewMsgBoxProc)));
SetDlgItemText(H, IDTRYAGAIN, '&Try again');
SetDlgItemText(H, IDCONTINUE, 'Contin&ue');
SetDlgItemText(H, ID_CANCEL, '&Cancel');
SetDlgItemText(H, ID_RETRY, '&Retry');
SetDlgItemText(H, IDIGNORE, '&Ignore');
SetDlgItemText(H, IDABORT, '&Abort');
SetDlgItemText(H, ID_HELP, '&Help');
SetDlgItemText(H, ID_YES, '&Yes');
SetDlgItemText(H, ID_NO, '&No');
end;
end;
case Msg of
WM_INITDIALOG :
begin
ActiveWindowHandle := AHWnd;
end;
//...
Przykład użycia - jak standardowego okienka:
begin
if MsgBox(ActiveWindowHandle, 'Exit from program, are you sure?' + #13#10 +
'You can disable this confirmation in application settings.', App_Title,
MB_ICONQUESTION + MB_YESNO + MB_DEFBUTTON1) = IDNO then
begin
//...
end;
- Rejestracja:ponad 15 lat
- Ostatnio:ponad 10 lat
Mam jeszcze jedno pytanie. MessageBox potrzebuje flagi która odpowiada za to jakie przyciski wybrałem itp ale zwraca ta flaga wartość int. Czy jest jakiś sposób aby rozpoznać w tym int'cie jakich przycisków uzyłem? NP: otrzymam 10 - i skad windows wie że chce przykładowo tak, nie i anuluj ?

- Rejestracja:ponad 13 lat
- Ostatnio:około 10 godzin
- Lokalizacja:Tuchów
- Postów:12171
A czytałeś kiedykolwiek jakąkolwiek dokumentację tej funkcji? Jasno jest w nich napisane o flagach, ich wartościach oraz o wartościach zwracanych przez tą funkcję; Wszelkie stałe są w module Windows
;
Ilość i tym przycisków:
MB_OK: 0
MB_OKCANCEL: 1
MB_ABORTRETRYIGNORE: 2
MB_YESNOCANCEL: 3
MB_YESNO: 4
MB_RETRYCANCEL: 5
MB_HELP: 16384
Wartości zwracane przez tą funkcję (czyli wartość stałej, jaka reprezentuje dany przycisk):
IDOK: 1
IDCANCEL: 2
IDABORT: 3
IDRETRY: 4
IDIGNORE: 5
IDYES: 6
IDNO: 7
IDTRYAGAIN: 10
IDCONTINUE: 11
- Rejestracja:ponad 15 lat
- Ostatnio:ponad 10 lat
Tak, czytałem dokumentację :) źle mnie zrozumiałeś, nie chodzi mi o to jaki przycisk został wciśnięty, tylko jakie przyciski mają się pokazać na oknie. Chodzi o to że tą flagę mam w bardzo wielu miejscach w programie, i chciałbym dalej ją interpretować we własnym oknie. Oczywiście mogę szukać te wszystkie miejsca w których "tworzę" tą flagę, aczkolwiek wolałbym tego uniknąć.
Dokładniej: Jeżeli tworzę okno z MB_OK i MB_ABORTRETRYIGNORE to w jaki sposób windows wie że akurat chcę te 4 przyciski a nie jakieś inne? Funkcja zwraca wartość int wiec w tym przypadku 2.

- Rejestracja:około 17 lat
- Ostatnio:około 3 lata
- Lokalizacja:Szczecin
- Postów:4191
Nie bardzo rozumiem, funkcja i Windows "wiedzą to", bo przekazałeś im to jako paramatr, a dalej wszystko ogarnia kod, który jest w systemowych bibliotekach. To tak jakbyś pytał skąd jakaś funkcja Sumuj(3, 2);
ma Tobie zwrócić 5. Po prostu za to odpowiada jej kod. Chyba, że nie o to pytasz :/

- Rejestracja:ponad 13 lat
- Ostatnio:około 10 godzin
- Lokalizacja:Tuchów
- Postów:12171
Bieluus napisał(a)
Dokładniej: Jeżeli tworzę okno z MB_OK i MB_ABORTRETRYIGNORE to w jaki sposób windows wie że akurat chcę te 4 przyciski a nie jakieś inne?
A skąd ja mam wiedzieć skąd Windows wie?
Czy Tobie chodzi o to w jaki sposób zostaje rozpoznany typ przycisków i według przekazanej wartości zostały uwidocznione tylko wybrane przyciski? Od tego jest argument uTypes: Cardinal
- do niego pakuje się różne flagi, które potem pewnie przez przesunięcie bitowe i koniunkcję zostają wydobyte z liczby i sprawdzone w bloku warunkowym/wyboru; Przynajmniej tak ja to widzę - w ten sposób tworzę własne okna dialogowe oraz wykorzystuję taką metodę w innych rzeczach, dzięki czemu w jednej liczbie można zapisać kilka różnych informacji, które potem można bardzo łątwo wypakować;
Jeśli chcesz wiedzieć dokładnie jak jest to zaimplementowane to przepatrz źródła - być może znajdziesz definicję funkcji MessageBox
;
Bieluus napisał(a):
Dokładniej: Jeżeli tworzę okno z MB_OK i MB_ABORTRETRYIGNORE to w jaki sposób windows wie że akurat chcę te 4 przyciski a nie jakieś inne? Funkcja zwraca wartość int wiec w tym przypadku 2.
Poczytaj o maskach bitowych, o ile dobrze zrozumiałem o co Tobie chodzi.
Const Flaga1 = 1;
Flaga2 = 2;
Flaga3 = 4;
Flaga4 = 8;
Flaga5 = 16;
Flaga6 = 32;
// i tak dalej
{...}
Var Flagi: LongWord;
Begin
Flagi := Flaga4 or Flaga6 {...};
{...}
if (Flagi and Flaga5) = Flaga5 Then
Begin
Flaga5 włączona;
End;
End;
- Rejestracja:ponad 15 lat
- Ostatnio:ponad 10 lat
Poczytam o tych przesunięciach bitowych o których mówił Furious Programming i może dam radę. Jest to dla mnie nowa rzecz ("ingerowanie w funkcje" WinApi) więc pewnie będzie to robione metodą prób i błędów aczkolwiek mam nadzieję ze za którymś razem się uda.
Zarejestruj się i dołącz do największej społeczności programistów w Polsce.
Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.