Я думаю, TConversationForm
- это окно верхнего уровня.Используйте EnumWindows
, чтобы найти это.(Пока не беспокойтесь о FindWindow
; он всегда возвращает первое найденное окно, поэтому, если активно несколько разговоров, у вас нет контроля над ним.)
type
PGetConversationParam = ^TGetConversationParam;
TGetConversationParam = record
ProcID: DWord;
ContactName: string;
Result: HWnd;
end;
function GetConversationWindow(Wnd: HWnd; P: LParam): Bool; stdcall;
var
Param: PGetConversationParam;
ProcID: DWord;
// WndClass docs say maximum class-name length is 256.
ClassName: array[0..256] of Char;
WindowTitle: array[0..256] of Char;
begin
Result := True; // assume it doesn't match; keep searching
Param := PGetConversationParam(P);
GetWindowThreadProcessID(Wnd, @ProcID);
if ProcID <> Param.ProcID then
Exit;
if GetClassName(Wnd, ClassName, Length(ClassName)) = 0 then
Exit;
if StrComp(ClassName, 'TConversationForm') <> 0 then
Exit;
if SendMessage(Wnd, wm_GetText, Length(WindowTitle), LParam(@WindowTitle[0])) = 0 then
Exit;
if Param.ContactName = WindowTitle then begin
Param.Result := Wnd;
Result := False;
end;
end;
ЭтоФункция проверяет несколько вещей, чтобы убедиться, что смотрит в нужное окно.Он проверяет, что окно принадлежит процессу Skype, что у него есть ожидаемый класс окна, и что его заголовок является именем целевого контакта.Если Skype добавляет дополнительный текст в заголовок окна, вам нужно убедиться, что он выглядит «достаточно близко».Не просто позвоните по номеру Pos
, чтобы узнать, появляется ли имя контакта где-то в заголовке;если у какого-либо контакта есть имя, которое является подстрокой заголовка окна беседы, вы можете случайно найти совпадение, если не должны.
Идентификатор процесса не является строго обязательным, поэтомуВы можете опустить эту часть, если не знаете идентификатор процесса.
Функция EnumWindows
будет вызывать вышеуказанную функцию один раз для каждого окна верхнего уровня.Если окно является тем, которое вы ищете, GetConversationWindow
возвращает False , чтобы сказать: «Я нашел то, что хочу, поэтому, пожалуйста, перестаньте спрашивать больше».В противном случае возвращается Верно : «Это был не тот, поэтому, пожалуйста, дайте мне другой».Если GetConversationWindow
когда-либо вернет False , то EnumWindows
также вернет False , а поле Param.Result
будет содержать дескриптор искомого окна.Если у вас есть это, используйте FindWindowEx
для навигации по остальной иерархии окон:
var
Param: TGetConversationParam;
begin
Param.ProcID := GetSkypeProcessID;
Param.ContactName := GetSkypeContactName;
if EnumWindows(@GetConversationWindow, LParam(@Param)) then
Abort; // Didn't find it.
// Param.Result holds the conversation window's handle. Now walk its children.
ControlWnd := FindWindowEx(Param.Result, 0, 'TChatEntryControl', nil);
if ControlWnd = 0 then
Abort; // Conversation doesn't have an entry control
RichEditWnd := FindWindowEx(ControlWnd, 0, 'TChatRichEdit', nil);
if RichEditWnd = 0 then
Abort;
// Voila!
end;