Priviet Malcziki!
Mam pytanko, czego ma użyć w WinApi zamiast
Application.ProcessMesages;
Wiem że mogę to chyba też użyć ale muszę dodać Forms a tego nie chcę
To wszystko na razie.
Priviet Malcziki!
Mam pytanko, czego ma użyć w WinApi zamiast
Application.ProcessMesages;
Wiem że mogę to chyba też użyć ale muszę dodać Forms a tego nie chcę
To wszystko na razie.
tak wyglada processmessages od kuchni:
function TApplication.IsDlgMsg(var Msg: TMsg): Boolean;
begin
Result := False;
if FDialogHandle <> 0 then
Result := IsDialogMessage(FDialogHandle, Msg);
end;
function TApplication.IsMDIMsg(var Msg: TMsg): Boolean;
begin
Result := False;
if (MainForm <> nil) and (MainForm.FormStyle = fsMDIForm) and
(Screen.ActiveForm <> nil) then
Result := TranslateMDISysAccel(MainForm.ClientHandle, Msg);
end;
function TApplication.IsKeyMsg(var Msg: TMsg): Boolean;
var
Wnd: HWND;
begin
Result := False;
with Msg do
if (Message >= WM_KEYFIRST) and (Message <= WM_KEYLAST) then
begin
Wnd := GetCapture;
if Wnd = 0 then
begin
Wnd := HWnd;
if (MainForm <> nil) and (Wnd = MainForm.ClientHandle) then
Wnd := MainForm.Handle
else
begin
// Find the nearest VCL component. Non-VCL windows wont know what
// to do with CN_BASE offset messages anyway.
// TOleControl.WndProc needs this for TranslateAccelerator
while (FindControl(Wnd) = nil) and (Wnd <> 0) do
Wnd := GetParent(Wnd);
if Wnd = 0 then Wnd := HWnd;
end;
if SendMessage(Wnd, CN_BASE + Message, WParam, LParam) <> 0 then
Result := True;
end
else if (LongWord(GetWindowLong(Wnd, GWL_HINSTANCE)) = HInstance) then
begin
if SendMessage(Wnd, CN_BASE + Message, WParam, LParam) <> 0 then
Result := True;
end;
end;
end;
function TApplication.IsHintMsg(var Msg: TMsg): Boolean;
begin
Result := False;
if (FHintWindow <> nil) and FHintWindow.IsHintMsg(Msg) then
CancelHint;
end;
function TApplication.ProcessMessage(var Msg: TMsg): Boolean;
var
Handled: Boolean;
begin
Result := False;
if PeekMessage(Msg, 0, 0, 0, PM_REMOVE) then
begin
Result := True;
if Msg.Message <> WM_QUIT then
begin
Handled := False;
if Assigned(FOnMessage) then FOnMessage(Msg, Handled);
if not IsHintMsg(Msg) and not Handled and not IsMDIMsg(Msg) and
not IsKeyMsg(Msg) and not IsDlgMsg(Msg) then
begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
end
else
FTerminate := True;
end;
end;
procedure TApplication.ProcessMessages;
var
Msg: TMsg;
begin
while ProcessMessage(Msg) do {loop};
end;
tak wygląda process messages od kuchni...dalej nie wiem jak ci pomóc...
Mozna by odebrac wszystkie lub kilka komunikatow z kolejki i przetworzyc je tak jak w petli komunikatow to robisz, ale osobiscie to ta czesc programu (niewiem co to, moze jakies obliczenia robisz, czy cos) umiescilbym w watku i obeszlo by sie bez tego.
O widze, ze ktos mnie uprzedzil i moja podpowiedz wydaje sie taka skromna
Kodzik ProcessMesages to i ja u siebie widziałem.
Z tego co go obczajam to widzę że trza chyba po prostu powtarzać komunikaty:
TranslateMessage(Msg);
DispatchMessage(Msg);
Aż Msg = 0
Poprawcie jeśli bardzo się pomyliłem
brawo misiek, doszedłeś do tego!
brawo misiek, doszedłeś do tego!
Tylko, ze te komunikaty dobrze byloby rozpoznac i obsluzyc, bo taki na pusto przesuwanie dalej to nie najlepsze rozwiazanie.
Ja rowniez proponuje skorzystac z wątów. Najlepiej wykorzystac klasę TThread. Bardzo wygodnie sie z nia pracuje.
Sorki trochę zaspałem z odpowiedzią.
Ja nie robię żadnych obliczeń, ja uruchamiam inny program (total cmd)
i muszę na niego poczekać później czekam aż pojawią się guziki 1,2,3 i programowo klikam na odpowiedni.
pomiędzy uruchomieniem się programu a pojawieniem się guzików muszę czekać, a jeśli nie ma tam ProcessMesages to totalcmd bardzo długo się uruchamia bo mój zajmuje proca szukaniem tego okna z guzikami.
Sorki trochę zaspałem z odpowiedzią.
Ja nie robię żadnych obliczeń, ja uruchamiam inny program (total cmd)
i muszę na niego poczekać później czekam aż pojawią się guziki 1,2,3 i programowo klikam na odpowiedni.
pomiędzy uruchomieniem się programu a pojawieniem się guzików muszę czekać, a jeśli NIE MA tam ProcessMesages to totalcmd bardzo długo się uruchamia bo mój zajmuje proca szukaniem tego okna z guzikami.
Skoro tak, to pomyśl o CreateProcess (ShellExecuteEx), WaitForSingleObject, WaitForInputIdle
//dopisek
Mały przykładzik:
PowerArchiver 2003.
Przy uruchamianiu pojawia się okienko (Klasa = TEvalForm, Text = PowerArchiver 2003) z kilkoma przyciskami (Klasa = TButton). Jeden z nich jest "wyłączony" i odbywa się odliczanie od 4 do 0. Po zakończeniu odliczania text na przycisku zmienia się na "Zgoda" i przycisk zostaje "włączony". Dopiero po kliknięciu na tym przycisku program się uruchamia.
Rozwiązanie :
program RunPowerArc;
uses
Windows,
SysUtils,
Messages,
ShellAPI;
const
App = 'E:\Programs\Compr\PowerArchiver 8.60\POWERARC.EXE';
function EnumChildProc(h: HWND; lPar: LPARAM): Bool; stdcall;
var
b1, b2: array[0..99] of Char;
begin
GetClassName(h, b1, SizeOf(b1));
GetWindowText(h, b2, SizeOf(b2));
if (string(b1) = 'TButton') and (string(b2) = '4') then
begin
EnableWindow(h, True); // włączenie buttona
SendMessage(h, BM_CLICK, 0, 0); // kliknięcie
end;
Result := True;
end;
var
sei: TShellExecuteInfo;
h: HWND;
begin
FillChar(sei, SizeOf(sei), 0);
with sei do
begin
cbSize := SizeOf(sei);
lpFile := PChar(App);
nShow := SW_SHOW;
fMask := SEE_MASK_NOCLOSEPROCESS;
end;
if not ShellExecuteEx(@sei) then
begin
MessageBox(0, 'ShellExecuteEx Failed !', 'Error ', MB_OK or MB_ICONEXCLAMATION);
Exit;
end;
if WaitForInputIdle(sei.hProcess, INFINITE) = WAIT_FAILED then
begin
MessageBox(0, 'WaitForInputIdle Failed !', 'Error', MB_OK or MB_ICONEXCLAMATION);
Exit;
end;
h := FindWindow('TEvalForm', 'PowerArchiver 2003');
if IsWIndow(h) then
EnumChildWindows(h, @EnumChildProc, 0);
end.
Ja nie robię żadnych obliczeń, ja uruchamiam inny program (total cmd)
i muszę na niego poczekać później czekam aż pojawią się guziki 1,2,3 i programowo klikam na odpowiedni.
Ja rozwiąząłem ten problem nieco inaczej - po uruchomieniu Commandera dałem sleep(1000) i to rozwiązało moje problemy.