Witam,
chciałbym w tym wątku zamieszczać po kolei kilka procedur na które patrząc - mówię sobie "na pewno można to skrócić o połowę - tylko jak?".
Proszę Was o wskazówki dotyczące optymalizacji poniższej procedury. Na pierwszy odstrzał procedurka, która odpowiada za 'odgrywanie' schematu który zawiera instrukcje typu 'przenieś kursor na kontrolkę', 'wyślij tekst do aktywnego okna', 'wyślij klawisz specjalny', itp.
Jeżeli chcecie zobaczyć co kryje się w którejś z procedury wywoływanej wewnątrz - to piszcie w komentarzu, a załączę kod.
procedure TfrmMenu.PlaySchema;
var
kmbControl_Pos_x, kmbControl_Pos_y: integer;
On_Control_Click_x, On_Control_Click_y: integer;
On_Window_Click_x, On_Window_Click_y: integer;
Window_Pos_x, Window_Pos_y: integer;
ControlFound: boolean;
Comment, Loop: string;
sciezkaPliku: string;
id_action: integer;
CursorPos: TPoint;
Target: HWND;
lpPowtorzen: integer;
label Petla;
begin
Action_Stopped := False;
AllowPlay(False);
ControlFound := False;
lpPowtorzen := 0;
Application.ProcessMessages;
IBDataSet_Instructions.First;
Petla:
while not IBDataSet_Instructions.Eof do
begin
if IBDataSet_InstructionsCHECKED.Value = 0 then
begin
IBDataSet_Instructions.Next;
Continue;
end;
if IBDataSet_InstructionsID_ACTION.Value = Action_MouseMove then
begin
// Mouse move loop - animate recorded mouse movements
while not IBDataSet_MousePath.Eof do
begin
Mouse_Event(MOUSEEVENTF_ABSOLUTE or MOUSEEVENTF_MOVE, (IBDataSet_MousePathX.Value) * 65535 div Screen.Width, (IBDataSet_MousePathY.Value) * 65535 div Screen.Height, 0, GetMessageExtraInfo);
Application.ProcessMessages;
Sleep(_playing_MouseCursorSpeed);
if Action_Stopped then
break;
IBDataSet_MousePath.Next;
end;
IBDataSet_Instructions.Next;
Continue; // Step to next instruction
end;
if Action_Stopped then
break;
id_action := IBDataSet_InstructionsID_ACTION.Value;
Window_ClassName := IBDataSet_InstructionsWINDOW_NAME.Value;
Control_ClassName := IBDataSet_InstructionsCONTROL_NAME.Value;
Control_Caption := IBDataSet_InstructionsCONTROL_CAPTION.Value;
sciezkaPliku := IBDataSet_InstructionsAPP_PATH.Value;
WaitTime := IBDataSet_InstructionsWAITTIME.Value;
Comment := IBDataSet_InstructionsCOMMENT.Value;
On_Control_Click_x := IBDataSet_InstructionsON_CONTROL_CLICK_LEFT.Value;
On_Control_Click_y := IBDataSet_InstructionsON_CONTROL_CLICK_TOP.Value;
On_Window_Click_x := IBDataSet_InstructionsON_WINDOW_CLICK_LEFT.Value;
On_Window_Click_y := IBDataSet_InstructionsON_WINDOW_CLICK_TOP.Value;
Window_Pos_x := GetWindowPos(Window_ClassName, Control_Caption).X;
Window_Pos_y := GetWindowPos(Window_ClassName, Control_Caption).Y;
if id_action = Action_SetCursorPos then
begin
Tray.BalloonHint(AppName, 'Ustawiam pozycję kursora', btInfo, 5000, True);
Mouse_Event(MOUSEEVENTF_ABSOLUTE or MOUSEEVENTF_MOVE, (On_Window_Click_X * 65535) div Screen.Width, (On_Window_Click_Y * 65535) div Screen.Height, 0, GetMessageExtraInfo);
IBDataSet_Instructions.Next;
Continue; // Step to next instruction
end;
if id_action = Action_WaitTime then
begin
Sleep(WaitTime);
IBDataSet_Instructions.Next;
Continue;
end;
if (id_action <> Action_RunFile) and (id_action <> Action_Condition) then
begin
if edtPowtorzen.Text = '0' then
Loop := 'Nieskończenie wiele / ' + IntToStr(lpPowtorzen)
else
Loop := IntToStr(lpPowtorzen) + '/' + edtPowtorzen.Text;
Tray.BalloonHint(AppName, 'Szukam okna...', btInfo, 5000, True);
Foreground := FindWindow(PChar(Window_ClassName), nil);
frmdm.Debug(Window_ClassName + ' - ' + IntToStr(Foreground));
if (Foreground = 0) then
begin
Tray.BalloonHint(AppName, 'Nie znaleziono okna [' + Window_ClassName + ']!', btWarning, 5000, True);
StopSchema;
Application.MessageBox(PChar('Nie znaleziono okna [' + Window_ClassName + ']!'), 'Błąd', MB_ICONWARNING);
Break;
end;
if IsIconic(Foreground) and (Foreground <> 0) then
begin
Tray.BalloonHint(AppName, 'Przywracam okno...', btInfo, 5000, True);
ShowWindow(Foreground, SW_SHOW);
ShowWindow(Foreground, SW_RESTORE);
frmdm.Debug(Window_ClassName + ' - pokaż okno');
end;
if Pos('#', Window_ClassName) = 0 then
begin
BringWindowToTop(Foreground); // dla pewnosci - wysun na wierzch
SetForegroundwindow(Foreground); // ustaw aktywne okno
end;
// Send Special Key to window
if IBDataSet_InstructionsID_ACTION.Value = Action_SpecialKey then
begin
if IBDataSet_InstructionsCOMMENT.Value = '[ENTER]' then
begin
keybd_event(Ord(VK_RETURN),0,0,0);
keybd_event(Ord(VK_RETURN),0,KEYEVENTF_KEYUP,0);
end;
if IBDataSet_InstructionsCOMMENT.Value = '[TAB]' then
begin
keybd_event(Ord(VK_TAB),0,0,0);
keybd_event(Ord(VK_TAB),0,KEYEVENTF_KEYUP,0);
end;
if IBDataSet_InstructionsCOMMENT.Value = '[ESC]' then
begin
keybd_event(Ord(VK_ESCAPE),0,0,0);
keybd_event(Ord(VK_ESCAPE),0,KEYEVENTF_KEYUP,0);
end;
if IBDataSet_InstructionsCOMMENT.Value = '[BACKSPACE]' then
begin
keybd_event(Ord(VK_BACK),0,0,0);
keybd_event(Ord(VK_BACK),0,KEYEVENTF_KEYUP,0);
end;
Sleep(WaitTime);
IBDataSet_Instructions.Next;
Continue;
end;
kbmControlInfo.Close;
kbmControlInfo.Open;
frmdm.Debug(Window_ClassName + ' - Pobierz uchwyty okien');
Tray.BalloonHint(AppName, 'Pobieram listę obiektów...', btInfo, 5000, True);
EnumChildWindows(ForeGround, @EnumChildWinProc, 0);
frmdm.Debug(Window_ClassName + ' (' + Control_ClassName + '): X = ' + IntToStr(kbmControlInfoControlPos_Left.Value));
frmdm.Debug(Window_ClassName + ' (' + Control_ClassName + '): Y = ' + IntToStr(kbmControlInfoControlPos_Top.Value));
Application.ProcessMessages;
if Foreground <> 0 then
begin
Tray.BalloonHint(AppName, 'Szukam obiektu...', btInfo, 5000, True);
ControlFound := False;
// 1. Ma klasę i ma nie zmieniony caption
if (Control_ClassName <> '') and (Control_Caption <> '') then
ControlFound := kbmControlInfo.Locate('WindowClass_Name;ControlName;ControlCaption', VarArrayOf([Window_ClassName, Control_ClassName, Control_Caption]), []);
// 1. ma klasę ale nie ma captiona
if not ControlFound then
if (Control_ClassName <> '') and (Control_Caption = '') then
ControlFound := kbmControlInfo.Locate('WindowClass_Name;ControlName', VarArrayOf([Window_ClassName, Control_ClassName]), []);
// ma klasę i inny caption
if not ControlFound then
if (Control_ClassName <> '') then
ControlFound := kbmControlInfo.Locate('WindowClass_Name;ControlName', VarArrayOf([Window_ClassName, Control_ClassName]), []);
// znaleziono ale caption jest inny to oznacz jako nie znaleziony
if ControlFound then
if Control_Caption <> kbmControlInfoControlCaption.Value then
ControlFound := False
else
if Control_Name <> kbmControlInfoControlName.Value then
ControlFound := kbmControlInfo.Locate('WindowClass_Name;ControlClass;ControlName;ControlCaption', VarArrayOf([Window_ClassName, Control_ClassName, Control_Name, Control_Caption]), []);
kmbControl_Pos_x := kbmControlInfoControlPos_Left.Value; // pozycja X kontrolki
kmbControl_Pos_y := kbmControlInfoControlPos_Top.Value; // pozycja Y kontrolki
if ControlFound then
frmdm.Debug(Window_ClassName + ' (' + Control_ClassName + ') - znaleziono!')
else
frmdm.Debug(Window_ClassName + ' (' + Control_ClassName + ') - nie znaleziono!');
Application.ProcessMessages;
if ControlFound then
Mouse_Event(MOUSEEVENTF_ABSOLUTE or MOUSEEVENTF_MOVE, (kmbControl_Pos_X + On_Control_Click_X) * 65535 div Screen.Width, (On_Control_Click_Y + kmbControl_Pos_Y) * 65535 div Screen.Height, 0, GetMessageExtraInfo)
else
Mouse_Event(MOUSEEVENTF_ABSOLUTE or MOUSEEVENTF_MOVE, (Window_Pos_X + On_Window_Click_X) * 65535 div Screen.Width, (Window_Pos_Y + On_Window_Click_Y) * 65535 div Screen.Height, 0, GetMessageExtraInfo);
Application.ProcessMessages;
end;
end;
if id_action = Action_MouseLeftClick then
begin
Tray.BalloonHint(AppName, 'LPM', btInfo, 5000, True);
Mouse_Event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
Mouse_Event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
end;
if id_action = Action_MouseRightClick then
begin
Tray.BalloonHint(AppName, 'PPM', btInfo, 5000, True);
Mouse_Event(MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, 0);
Mouse_Event(MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0);
end;
if id_action = Action_MouseMiddleClick then
begin
Tray.BalloonHint(AppName, 'ŚPM', btInfo, 5000, True);
Mouse_Event(MOUSEEVENTF_MIDDLEDOWN, 0, 0, 0, 0);
Mouse_Event(MOUSEEVENTF_MIDDLEUP, 0, 0, 0, 0);
end;
if id_action = Action_RunFile then // Run
begin
// if process exists then kill process
if IBDataSet_InstructionsAPP_RESTART.Value = 1 then
if processExists(ExtractFileName(sciezkaPliku)) then
KillTask(ExtractFileName(sciezkaPliku));
Application.ProcessMessages;
Sleep(50);
if IBDataSet_InstructionsMULTIPLE_INSTANCES.Value = 0 then
// if process exists then do not run another copy
if processExists(ExtractFileName(sciezkaPliku)) then
begin
IBDataSet_Instructions.Next;
Continue;
end;
Tray.BalloonHint(AppName, 'Uruchamiam plik...', btInfo, 5000, True);
if not RunFile(sciezkaPliku) then
begin
Tray.BalloonHint(AppName, 'Nie znaleziono pliku źródłowego!', btWarning, 5000, True);
StopSchema;
Break;
end;
end;
if id_action = Action_Condition then
begin
Tray.BalloonHint(AppName, 'Sprawdzam warunek...', btInfo, 5000, True);
if Check_Condition(IBDataSet_InstructionsID_C.Value) then
begin
if not IBDataSet_Instructions.Locate('CONDITION_IDENTIFICATOR', IBDataSet_InstructionsID_TRUE.Value, []) then
begin
Tray.BalloonHint(AppName, 'Nie znaleziono warunku!', btWarning, 5000, True);
Application.MessageBox(PChar('Nie znaleziono identyfikatora warunku PRAWDA [' + frmdm.IBDataSet_CheckConditionID_TRUE.Value + ']!'), 'Nie znaleziono identyfikatora warunku', MB_ICONWARNING);
StopSchema;
Break;
end else
begin
Tray.BalloonHint(AppName, 'Warunek spełniony', btInfo, 5000, True);
Application.ProcessMessages;
Sleep(WaitTime);
IBDataSet_Instructions.Prior;
IBDataSet_Instructions.Next;
Continue;
end;
end else
begin
if not IBDataSet_Instructions.Locate('CONDITION_IDENTIFICATOR', IBDataSet_InstructionsID_FALSE.Value, []) then
begin
Tray.BalloonHint(AppName, 'Nie znaleziono warunku!', btWarning, 5000, True);
Application.MessageBox(PChar('Nie znaleziono identyfikatora warunku FAŁSZ [' + frmdm.IBDataSet_CheckConditionID_FALSE.Value + ']!'), 'Nie znaleziono identyfikatora warunku', MB_ICONWARNING);
StopSchema;
IBDataSet_Instructions.Next;
Continue;
end else
begin
Tray.BalloonHint(AppName, 'Warunek nie spełniony', btInfo, 5000, True);
Application.ProcessMessages;
Sleep(WaitTime);
IBDataSet_Instructions.Prior;
Continue;
end;
end;
end;
if id_action = Action_MouseDBClick then
begin
Tray.BalloonHint(AppName, 'Otwieram...', btInfo, 5000, True);
Mouse_Event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
Sleep(5);
Application.ProcessMessages;
Mouse_Event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
Sleep(5);
Application.ProcessMessages;
Mouse_Event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
Sleep(5);
Application.ProcessMessages;
Mouse_Event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
Application.ProcessMessages;
end;
if id_action = Action_TypeText then
begin
if ControlFound then
begin
if IBDataSet_InstructionsINPUTTEXT_MODE.Value = 1 then
Keyboard_SendText(Comment) // Keyboard
else begin // Cursor
SendMessage(kbmControlInfoHandle.Value, WM_SETTEXT, 0, integer(PChar(Comment)));
SendMessage(kbmControlInfoHandle.Value, EM_SETSEL, length(Comment), length(Comment));
end;
Tray.BalloonHint(AppName, 'Wysłano tekst', btInfo, 5000, True);
end else
begin
GetCursorPos(CursorPos);
Target := WindowFromPoint(CursorPos);
if Target <> 0 then
begin
if IBDataSet_InstructionsINPUTTEXT_MODE.Value = 1 then
Keyboard_SendText(Comment) // Keyboard
else begin // Cursor
SendMessage(Target, WM_SETTEXT, ord(True), LPARAM(PChar(Comment)));
SendMessage(Target, EM_SETSEL, length(Comment), length(Comment));
end;
Tray.BalloonHint(AppName, 'Wysłano tekst', btInfo, 5000, True);
end else
begin
Application.MessageBox('Nie wysłano tekstu [Nie można odwołać się do obiektu]', 'Błąd wysyłania tekstu', MB_ICONWARNING);
StopSchema;
Tray.BalloonHint(AppName, 'Nie wysłano tekstu [Nie można odwołać się do obiektu]', btWarning, 5000, True);
Break;
end;
end;
end;
Application.ProcessMessages;
Sleep(WaitTime);
{end else
begin
Application.MessageBox(PChar('Nie znaleziono kontrolki [' + nazwaKontrolki + '] !'), 'Błąd', MB_ICONWARNING);
StopSchema;
Break;
end; }
IBDataSet_Instructions.Next;
end;
if not Action_Stopped and not (edtPowtorzen.Text = '1') then
repeat
Inc(lpPowtorzen);
if StrToInt(edtPowtorzen.Text) = 0 then
lpPowtorzen := -1; // nieskończenie wiele
if lpPowtorzen < StrToInt(edtPowtorzen.Text) + 1 then
goto Petla;
until (lpPowtorzen = StrToInt(edtPowtorzen.Text) + 1) or Action_Stopped;
StopSchema;
AllowPlay(True);
Beep;
Tray.BalloonHint(AppName, 'Zakończono odtwarzanie.', btInfo, 5000, True);
end;