Witam.
Otwieram plik .txt poprzez ShellExecute w Notatniku i chciałbym wykryć moment ukazania się na ekranie okna Notatnika z wczytanym plikiem.txt. Podobnie ma się sytuacja z Word'em ale w tym przypadku chciałbym wykryć moment wyświetlenia na ekranie okna głównego z zawartością pliku a nie splash'a
Proszę o podpowiedzi gdzie szukać
Pozdrawiam.
Jest możliwośc wywołania ShellExecuteEx tak, aby zwróciło PID procesu. Jednak przykładowy kod mogę pokazać dopiero jutro wieczorem, gdyż nie mam dostępu do swojego PC w tej chwili. Mając już PID, który łatwiej uzyskać z funkcji CreateProces. Mozemy używając funkcji EnumWindows w połączeniu z GetWindowThreadProcessId uzyskać konktetny uchwyt. Oczywiście CreateProcess, pozwala na uruchomienie plików wykonywalnych, a nie skojarzonych. Więcej informacji na MSDN, a przykłady na mnóstwie stron, które trzeba sobie wygooglować.
Możesz też spróbować użyć funkcji FindWindow i w parametrze podać nazwę okna np.
dla nazwy pliku "test.txt":
"test.txt – Notatnik" (zwróć uwagę na niestandardowy myślnik)
"test.txt - Microsoft Word"
function GetWordWindowByDocFileName(ADocFileName: string): THandle;
const
MSWORD_WND_CLASS_NAME = 'OpusApp';
MSWORD_WND_CAPTION_SUFIX = ' - Microsoft Word';
var
WordWndCaption: string;
begin
WordWndCaption:= ChangeFileExt(ADocFileName, '') + MSWORD_WND_CAPTION_SUFIX;
result:= FindWindow(MSWORD_WND_CLASS_NAME, PChar(WordWndCaption));
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
if GetWordWindowByDocFileName('test.doc') > 0 then
begin
Timer1.Enabled:= False;
ShowMessage('Uruchomiłeś Worda!!!');
end;
end;
kAzek napisał(a):
function GetWordWindowByDocFileName(ADocFileName: string): THandle;
const
MSWORD_WND_CLASS_NAME = 'OpusApp';
MSWORD_WND_CAPTION_SUFIX = ' - Microsoft Word';
var
WordWndCaption: string;
begin
WordWndCaption:= ChangeFileExt(ADocFileName, '') + MSWORD_WND_CAPTION_SUFIX;
result:= FindWindow(MSWORD_WND_CLASS_NAME, PChar(WordWndCaption));
end;
Nie mam w tej chwili możliwości sprawdzenia jaki jest format captiona okna Worda z wczytanym dokumentem, ale z tego co pamiętam, to może być np. taki: "Dokument.doc - Microsoft Word", a nie "Dokument - Microsoft Word", więc formatowanie tekstu przypisanego do "WordWndCaption" nie będzie prawidłowe, bo jest wycinane rozszerzenie ".doc" i okno Worda nie będzie znalezione.
Pomysł na wyszukiwanie oczywiście jak najbardziej spoko.
Dziękuję wszystkim za zainteresowanie.
Pomysł z listą okien jest najlepszy, a sprawdzenie nazwy lub fragmentu nazwy pliku w nazwie okna realizuje przez funkcję "pos".
Dla zainteresowanych podaję funkcję zapisującą do
TStringList
nazwy okien aplikacji uruchomionych w systemie. Funkcja FindWindow
nie działąła mi prawidłowo przy Windows 7.
```delphi
function AllWindows(wHnd: THandle; List: TStringList): Bool; stdcall;
var Buffer: array[0..255] of char;
begin
SendMessage(wHnd, WM_GETTEXT, 255, LongInt(@Buffer[0]));
if (Buffer <> '') and IsWindow(wHnd) then
begin
List.AddObject(Buffer, TObject(wHnd));
end;
Result := True;
end.
Pozdrawiam.
Moduł zwracający PID przy wywołaniu przez funkcję ShellExecAndGetPid
dołączam do tego posta. A i co to znaczy, że pod Windows 7 FindWindow
źle Tobie działa? Używałem jej wielokrotnie na Windowsie 7 Ultimate 64 bit. I nie było żadnych problemów. Być może jednak, w jakimś przypadku musisz rozpoznać tytuł po UNICODE
, to wtedy użyj FindWindowW
.
Można też coś takiego:
uses
ShellApi;
//funkcja dostepna od Windows XP SP1
function GetProcessId(hProcess: Cardinal): Cardinal; stdcall; external 'kernel32.dll';
procedure TForm1.Button1Click(Sender: TObject);
var
Info: TShellExecuteInfo;
hWin: HWND;
PID, PIDCurrentWnd: Cardinal;
len: Integer;
buff: string;
begin
ZeroMemory(@Info, SizeOf(TShellExecuteInfo));
Info.cbSize:= SizeOf(TShellExecuteInfo);
Info.fMask:= SEE_MASK_NOCLOSEPROCESS;
Info.nShow:= SW_NORMAL;
Info.lpFile:= 'c:\Users\kAzek\Documents\test.docx';
if ShellExecuteEx(@Info) then
begin
PID:= GetProcessID(Info.hProcess);
WaitForInputIdle(Info.hProcess, INFINITE);
repeat
hWin:= GetForegroundWindow;
while (hWin <> 0) do
begin
GetWindowThreadProcessID(hWin, PIDCurrentWnd);
if PIDCurrentWnd = PID then
begin
len:= GetWindowTextLength(hWin) + 1;
SetLength(buff, len);
len:= GetWindowText(hWin, PChar(buff), len);
SetLength(buff, len);
if (Pos('Microsoft Word', buff) > 0) and (Pos('test', buff) = 1) then
break;
end;
hWin:= GetNextWindow(hWin, GW_HWNDNEXT);
end;
Sleep(100);
Application.ProcessMessages;
until (hWin <> 0);
ShowMessage('Zaladowany!');
end;
end;