Pytanko o WinApi

0

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.

0

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...

0

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

0

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

0

brawo misiek, doszedłeś do tego!

0

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.

0

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.

0

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.
0

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.

1 użytkowników online, w tym zalogowanych: 0, gości: 1