Witam.
czy jest jakiś sposób aby wstawić taką ikonę UINT uType z
MessageBox
na formę? Załóżmy że mam czystą formę i co dalej?
Jeśli tej nie da rady to może jakaś inna w zastępstwie.
Pozdrawiam
Witam.
czy jest jakiś sposób aby wstawić taką ikonę UINT uType z
MessageBox
na formę? Załóżmy że mam czystą formę i co dalej?
Jeśli tej nie da rady to może jakaś inna w zastępstwie.
Pozdrawiam
Można kombinować z CreateMessageDialog
pod VCL i sobie tak jak tutaj podmieniam tę ikonę na aplikacji, pobrać ją przez Assign
do jakiegoś innego TImage
.
procedure TMainForm.ShowMsgDlgButtonClick(Sender: TObject);
var
Dlg : TForm;
CBX : TCheckBox;
begin
Dlg := CreateMessageDialog('Czy na pewno chcesz zamknąć program?',
mtConfirmation, [mbYes, mbNo]);
Dlg.Caption := Application.Title;
Dlg.BorderIcons := [];
Dlg.Height := 130;
Dlg.ActiveControl := TButton(Dlg.FindComponent('Yes'));
TImage(Dlg.FindComponent('Image')).Picture.Assign(Application.Icon);
TButton(Dlg.FindComponent('Yes')).Caption := 'Tak';
TButton(Dlg.FindComponent('No')).Caption := 'Nie';
TButton(Dlg.FindComponent('Yes')).Top := 70;
TButton(Dlg.FindComponent('No')).Top := 70;
CBX := TCheckBox.Create(Dlg);
CBX.Parent := Dlg;
CBX.Caption := 'Zawsze pytaj';
CBX.Left := (Dlg.Width - CBX.Width) div 2;
CBX.Top := 40;
CBX.Checked := False;
CBX.OnClick := CBXOnClick;
Dlg.ShowModal;
case Dlg.ModalResult of
mrYes : begin
Caption := 'Tak';
end;
mrNo : begin
Caption := 'NIE';
end;
end;
if CBX.Checked then
begin
Caption := Caption + #32 + '- Zaznaczony';
end
else
begin
Caption := Caption + #32 + '- Odznaczony';
end;
end;
Tylko wiadomo, taki obrazek będzie tym co zaprojektowali twórcy IDE typu Delphi czy Lazarus. A pod tym pierwszym na pewno nie będzie to w pełni idelnie systemowa grafika. Przynajmniej tak się mi zdaje. Natomiast pod WinAPI nie próbowałem tego, ale na logikę można kombinować tak jak poniżej. Najpierw jakaś stała. Przykładowo:
const
WM_CHANGEMSGBOX = WM_USER + 2012;
I dodać sobie własną funkcję do wywołania MessageBoxa
. Poniżej akutat żywcem kopiowiane z mojego kodu w WinAPI. Ale pod VCL możesz sobie tam podstawić uchwyt głownej formatki, tylko ważne żeby Formatka obsługiwała ten komunikat w swoim WndProc
, czyli musisz subclassować na przykład.
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;
Ważne jest żeby było PostMessage
, a nie Send
, bo może nie zadziałać gdyż czeka na efekty. Ok. To teraz trzeba obsłużyć komunikat we WndProc
formatki lub naszego okna czy dialogu. Na przykład tak:
//...
if Msg = WM_CHANGEMSGBOX then
begin
H := FindWindow(WC_DIALOG, nil);
if GetParent(H) = AHWnd then
begin
PNewMsgBoxProc := @MsgBoxProc;
POldMsgBoxProc := Pointer(SetWindowLong(H, GWL_WNDPROC, Integer(PNewMsgBoxProc)));
if (AWParam and MB_OKCANCEL > 0)
or (AWParam and MB_YESNOCANCEL > 0) then
begin
SetDlgItemText(H, IDCANCEL, '&Cancel');
end;
SetDlgItemText(H, IDTRYAGAIN, 'Try again');
SetDlgItemText(H, IDCONTINUE, 'Continue');
SetDlgItemText(H, IDIGNORE, 'Ignore');
SetDlgItemText(H, IDRETRY, 'Retry');
SetDlgItemText(H, IDABORT, 'Abort');
SetDlgItemText(H, IDHELP, '&Help');
SetDlgItemText(H, IDYES, '&Yes');
SetDlgItemText(H, IDNO, '&No');
end;
end;
//...
Jak widzisz sublassuje tutaj obsługę komunikatów okienka MessageBox
. Czyli można cudować w razie potrzeby na przykład, tak jak poniżej kiedy okienko się mi nie zamykało Escapem, a chciałem tego:
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;
Jak widzisz tutaj bez problemów dobierając się do funkcji obsługi komunikatów lub wcześniej mając już uchwyt tego tworzonego okienka. Nic nie stoi na przeszkodzie by sobie enumerować kontorlki z niego poprzez EnumChildWindows
i poprzez GetClassName
sprawdzić czy klasa to Static
i spróbować wysłać do kontrolki komunikat za pewne STM_GETICON
lub STM_GETIMAGE
. Jeżeli zwróci to nam uchwyt rózny od zera. Za pewne typu HICON
, to nic już nie stoi nam na przeszkodzie by podstawić go do TImage
, czy narysować go sobie na formatce albo na jakimś Canvasie. Lub na przykład zapisać do pliku.
Tak ja bym kombinował. Trzeba tylko sobie zrobić formatkę do testów i poenumerować do na przykład Memo
listę kontrolek z uchwytami oraz klasami. Żeby mieć pewność czy nie ma innych Staticów
w oknie i takie tam. I może są prostsze sposoby, ale ja tak bym kombinował i dla mnie sposób z wykorzystaniem WinAPI
, wydaje się najprostszy do zastosowania i nawet wręcz oczywisty.
EDIT: na szybko zrobiłem takie coś. Pokazałem sobie jakieś okienko MessageBox
ze swojego programu WinAPI z "aboutem". Ustaliłem uchwyt Static
z ikonką swoim prostym lamerskim programikiem WinInfo
, który tutaj kiedyś zapodawałem. I zrobiłem pod VCL na szybko:
Image1.Picture.Icon.Handle := SendMessage($603C8, STM_GETICON, 0, 0);
Ikona widoczna na MessageBox
pokazała się bez problemów na TImage
, także tak jak podejrzewałem, można w ten sposób śmiało zrobić i uzyskać bez większych problemów zamierzony efekt :)
http://msdn.microsoft.com/en-us/library/windows/desktop/ms648045%28v=vs.85%29.aspx
Dajesz chyba: OBM_EXCLAMATION - dokładnie nie pamiętam, kiedy to szukałem - znalazłem w google.
Ano fakt. Zapomniałem, że LoadImage
może też nam ładować standardowe grafiki, tak jak SetCursor
ustawiać systemowe kursory. No coż, na około pokombinowałem. Lecz może i taki sposób się też przyda szukającym, bo subclassując standardowego MessageBoxa
, mamy fajne możłiwości. Jak na przykład łatwe dodanie innych potrzebnych nam kontrolek w takim oknie bez potrzeby tworzenia własnego dialogu od zera :)
Ja w tej chwili mam dynamicznie tworzoną formę z tym komponentami> I właśnie pasowało by na niej umieścić ikonkę po prawej stronie z możliwością nawet dla ułatwienia tej samej zmiennej jak przy MessageBox np. IconWarnning, żeby to już było intuicyjne/ na zasadzie analogii.
Na początku procedury przymierzałem się do zmiennej uType: UINT; i w tym miejscu utknąłem. Zapewne dojdzie do tego położenie ikony, jakieś
IconX, IconY: Integer;
Poniższa forma jest testowa i na jej przykładzie chciałem zmajstrować kilka większych do pobierania i przetwarzania danych. Dlatego chciałem dopracować temat. Więc co by teraz należało tam wstawić? Powyższe przykłady też się przydadzą.
Przykładowy kod
// Okno dialogowe o zapisaniu lub wczytaniu pliku zrobione na podstawie InputQuery
procedure TDlgImpExp.FormCreate();
const
btWidth = 75;
var
btMarginX,btSpace: Integer;
uType: UINT; // http://4programmers.net/WinAPI/MessageBox
begin
uType:= MB_ICONQUESTION;
Form := TForm.Create(Application);
with Form do
try
Form.Font := Font;
Width := 300;
Height:= 160;
BorderStyle := bsDialog;
Position := poScreenCenter;
Caption := 'Wybór opcji.';
Name := 'Form';
lbPrompt := TLabel.Create(Form);
with lbPrompt do
begin
Parent := Form;
Caption := 'Informacja o .....';
Left := 16;
Top := 16;
Width:= fmDlgImpExp.Width - 32;
WordWrap := True;
Name := 'lbPrompt';
end;
btMarginX:= 30;
btSpace:= (Form.Width - (2*btMarginX) - (3*btWidth)) div 2;
btExport := TButton.Create(Form);
with btExport do
begin
Parent := Form;
Caption := 'Eksport';
Left := btMarginX;
Top := lbPrompt.Top +20 +lbPrompt.Height;
Width := btWidth;
Height:= 25;
Name := 'btExport';
OnClick:= btExportClick;
end;
{ kilka butonów ...............
}
Form.ShowModal;
finally
lbPrompt.Free;
btExport.Free;
....
Form.Free;
end;
end;
Skoro potrzebujesz okno dialogowe, wyglądające podobnie jak systemowe, ale z własnymi elementami, to dlaczego nie zrobisz sobie swojego? Dla okna funkcjonalnego jak MessageBox
to bardzo mało roboty - więcej klikania niż programowania;
Jeśli byłbyś zainteresowany zrobieniem własnego okna dialogowego według własnych wytycznych, to polecam swój artykuł pt. "Własne okna dialogowe", w którym to opisałem sposób na stworzenie prostego okna dialogowego (własny odpowiednik MessageBox
), jak i okna zwracającego dowolne dane (np. struktury).