Форум: "WinAPI";
Текущий архив: 2014.11.30;
Скачать: [xml.tar.bz2];
ВнизСписок запущенных приложений (тот что на панели задач). Найти похожие ветки
← →
Дмитрий С © (2010-04-06 09:46) [0]Хочу написать програмку для переключения задач для Windows Mobile. Решил поэкспериментировать на обычном windows 7.
Вобщем возникли вопросы:
1. Как этот самый список получить. Пробую так, вроде работает, правильно ли:Wnd := GetWindow(Application.Handle, gw_HWndFirst);
while Wnd <> 0 do
begin { Не показываем: }
if IsWindowVisible(Wnd) { Невидимые окна }
and (GetWindow(Wnd, gw_Owner) = 0) { Дочерние окна }
and (GetWindowText(Wnd, buff, sizeof(buff)) <> 0) { Окна без заголовков }
then
begin
GetWindowText(Wnd, buff, sizeof(buff));
ListBox1.Items.AddObject(StrPas(buff), TObject(Wnd));
end;
Wnd := GetWindow(Wnd, gw_hWndNext);
end;
Пример взял из сети.
Смущает такой факт: Откуда брать Application.Handle, если писать на winapi?
Может есть более правильный пример?
ToolHelp не хочу использовать.
2. Как правильно получить заголовок окна.
Теоретически ведь между GetWindowTextLength и GetWindowText заголовок окна может измениться, и выделенного буфера не хватит.
3. Как правильно получить иконку приложения. Делаю так:Ico := SendMessage(HWnd(Items.Objects[Index]), WM_GETICON, ICON_SMALL2, 0);
if Ico <= 0 then
Ico := GetClassLong(HWnd(Items.Objects[Index]), GCL_HICONSM);
if Ico > 0 then
DrawIconEx(Canvas.Handle, Rect.Left + 1, Rect.Top + 1, Ico, 16, 16, 0, 0, DI_NORMAL);
Нужно ли как-то освобождать Ico?
4. Как правильно активировать то или иное приложение?
Делаю так:Wnd := HWND(Items.Objects[ItemIndex]);
if IsIconic(Wnd) then
SendMessage(Wnd, WM_SYSCOMMAND, SC_RESTORE, 0);
SetForegroundWindow(Wnd);
5. Как правильно закрыть приложение.
Тут пока я никак не делаю, но думаю посылать WM_CLOSE или WM_QUIT. Как правильно, не знаю.
Подскажите, где что не так, где так и что почитать можно?
← →
Leonid Troyanovsky © (2010-04-06 11:34) [1]
> Дмитрий С © (06.04.10 09:46)
> 1. Как этот самый список получить. Пробую так, вроде работает,
> правильно ли:
Правильно - EnumWindows.
Для определения наличия кнопки на таскбаре можно использовать
нечто подобное http://rsdn.ru/forum/delphi/525933.aspx
> Откуда брать Application.Handle, если писать на winapi?
Брать то свое окно, которое имеет кнопку на таскбаре.
> Теоретически ведь между GetWindowTextLength и GetWindowText
> заголовок окна может измениться, и выделенного буфера не
> хватит.
GetWindowText возвращает количество считанного.
Можно взять буфер с заведомым запасом.
> Нужно ли как-то освобождать Ico?
IMHO, не нужно.
> Wnd := HWND(Items.Objects[ItemIndex]);
Хендлы окон не стоит хранить в списке, бо, необходимо поддерживать
его актуальность. Если это необходимо, нужно ставить хуки на потоки, владеющие этими окнами, для получения уведомлений о их разрушении.
> 5. Как правильно закрыть приложение.
> Тут пока я никак не делаю, но думаю посылать WM_CLOSE или
> WM_QUIT. Как правильно, не знаю.
Например, WM_QUIT каждому GUI потоку приложения.
Но, это тоже, не совсем корректно, бо с несохраненными данными
можно попрощаться.
Но, в любом случае, придется держать в запасе TeminateProcess.
--
Regards, LVT.
← →
DVM © (2010-04-06 15:53) [2]
> Как этот самый список получить.
EnumWindows() потом WH_SHELL ловушка или таймер и опять тот же EnumWindows(). Explorer похоже использует и таймер и WH_SHELL
Я вот так проверял когда то:
function IsAppWindow(Wnd: HWND): BOOL; stdcall;
var
Style, ExtStyle: LongInt;
hOwner, hParent: HWND;
begin
Result := true;
if not IsWindow(Wnd) then
begin
Result := false;
exit;
end;
Style := GetWindowLong(Wnd, GWL_STYLE);
ExtStyle := GetWindowLong(Wnd , GWL_EXSTYLE);
hOwner := GetWindow(Wnd, GW_OWNER);
hParent := GetParent(Wnd);
if (Style and WS_CHILD) <> 0 then result := false;
if (Style and WS_VISIBLE) = 0 then Result := false;
if not IsWindowVisible(Wnd) then Result := false;
if (ExtStyle and WS_EX_TOOLWINDOW) <> 0 then Result := false;
if (ExtStyle and WS_EX_MDICHILD) <> 0 then Result := false;
if (hOwner <> 0) and ((ExtStyle and WS_EX_APPWINDOW) = 0) then result := false;
if (hOwner <> 0) and Result then Result := not IsAppWindow(hOwner);
if hParent <> 0 then Result := false;
if GetWindowLong(Wnd , GWL_USERDATA) = MagicDWord then Result := false;
end; // End of function IsAppWindow;
← →
DVM © (2010-04-06 15:55) [3]
> 2. Как правильно получить заголовок окна.
> Теоретически ведь между GetWindowTextLength и GetWindowText
> заголовок окна может измениться, и выделенного буфера не
> хватит.
WH_SHELL кстати уведомляет об изменение заголовка или иконки
function GetTextFromWindow(hWnd: HWND): string;
var
TextLength: integer;
Text: PChar;
begin
TextLength := GetWindowTextLength(hWnd) + 1;
GetMem(Text, TextLength * SizeOf(Char));
GetWindowText(hWnd, Text, TextLength);
Result := Text;
FreeMem(Text, TextLength * SizeOf(Char));
end; // End of function GetTextFromWindow
> 3. Как правильно получить иконку приложения.
function _GetFileAssociatedIcon(FileName: string; bSmall: boolean): HICON;
var
FileInfo: SHFILEINFO;
BIG_OR_SMALL_ICON: integer;
begin
if bSmall then
BIG_OR_SMALL_ICON := SHGFI_SMALLICON
else
BIG_OR_SMALL_ICON := SHGFI_LARGEICON;
SHGetFileInfo(PChar(FileName),
FILE_ATTRIBUTE_NORMAL,
FileInfo,
SizeOf(FileInfo),
SHGFI_ICON or BIG_OR_SMALL_ICON or SHGFI_SYSICONINDEX);
Result := FileInfo.hIcon;
end;
//------------------------------------------------------------------------------
function _GetProcessFileNameByWindowHandle(Wnd: HWND): string;
var
hProcess: THandle;
PID: Cardinal;
FileName: array [1..MAX_PATH] of char;
PE: TProcessEntry32;
Snap: Cardinal;
OsVerInfo: TOSVersionInfo;
begin
Result := "";
GetWindowThreadProcessId(Wnd, @PID);
hProcess := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, false, PID);
OsVerInfo.dwOSVersionInfoSize := SizeOf(TOSVersionInfo);
if GetVersionEx(osVerInfo) then
begin
if OsVerInfo.dwPlatformId = VER_PLATFORM_WIN32_NT then
begin
ZeroMemory(@Filename[1], SizeOf(Filename));
GetModuleFileNameEx(hProcess, 0, @Filename[1], SizeOf(Filename));
Result := FileName;
end
else
begin
Snap := CreateToolHelp32SnapShot(TH32CS_SNAPPROCESS, 0);
if Snap <> -1 then
begin
PE.dwSize:=SizeOf(PE);
if Process32First(Snap, PE) then
repeat
if PE.th32ProcessID = PID then Result := PE.szExeFile;
until not Process32Next(Snap, PE);
end;
end;
end;
CloseHandle(hProcess);
end;
//------------------------------------------------------------------------------
function GetIconFromWindow(hWnd: HWND): HICON; stdcall;
const
ICON_SMALL2 = 2;
begin
Result := 0;
// Get Small Icon From Window ...
SendMessageTimeout(hWnd, WM_GETICON, ICON_SMALL, 0, SMTO_ABORTIFHUNG, 1000, Cardinal(Result));
if Result = 0 then SendMessageTimeout(hWnd, WM_GETICON, ICON_SMALL2, 0, SMTO_ABORTIFHUNG, 1000, Cardinal(Result));
if Result = 0 then Result := GetClassLong(hWnd, GCL_HICONSM);
if Result = 0 then SendMessageTimeout(hWnd, WM_GETICON, ICON_SMALL, 1,
SMTO_ABORTIFHUNG, 1000, Cardinal(Result));
if Result = 0 then SendMessageTimeout(hWnd, WM_GETICON, ICON_SMALL2, 1,
SMTO_ABORTIFHUNG, 1000, Cardinal(Result));
if Result = 0 then SendMessageTimeout(hWnd, WM_QUERYDRAGICON, ICON_SMALL,
0, SMTO_ABORTIFHUNG, 1000, Cardinal(Result));
if Result = 0 then SendMessageTimeout(hWnd, WM_QUERYDRAGICON, ICON_SMALL2,
0, SMTO_ABORTIFHUNG, 1000, Cardinal(Result));
// Get Big Icon From Window ...
if Result = 0 then SendMessageTimeout(hWnd, WM_GETICON, ICON_BIG, 0, SMTO_ABORTIFHUNG, 1000, Cardinal(Result));
if Result = 0 then Result := GetClassLong(hWnd, GCL_HICON);
if Result = 0 then SendMessageTimeout(hWnd, WM_GETICON, ICON_BIG, 1,
SMTO_ABORTIFHUNG, 1000, Cardinal(Result));
if Result = 0 then SendMessageTimeout(hWnd, WM_QUERYDRAGICON, ICON_BIG,
0, SMTO_ABORTIFHUNG, 1000, Cardinal(Result));
// Get Icon From File ...
if Result = 0 then Result := _GetFileAssociatedIcon(_GetProcessFileNameByWindowHandle(hWnd), true);
if Result = 0 then Result := _GetFileAssociatedIcon(_GetProcessFileNameByWindowHandle(hWnd), false);
// Load Default Icon ... }
if Result = 0 then Result := LoadIcon(0, IDI_APPLICATION);
end; // End of function GetIconFromWindow
← →
DVM © (2010-04-06 15:57) [4]
> 4. Как правильно активировать то или иное приложение?
Проводник пользуется недокументированной функцией SwitchToThesWindow, так что либо ей либо вот аналог
function ForceForegroundWindow(hWnd: HWND): BOOL; stdcall;
const
SPI_GETFOREGROUNDLOCKTIMEOUT = $2000;
SPI_SETFOREGROUNDLOCKTIMEOUT = $2001;
var
OsVerInfo: TOSVersionInfo;
Win32MajorVersion: Integer;
Win32MinorVersion: Integer;
Win32Platform: Integer;
ForegroundThreadID: DWORD;
ThisThreadID: DWORD;
Timeout: DWORD;
begin
OsVerInfo.dwOSVersionInfoSize := SizeOf(TOSVersionInfo);
GetVersionEx(osVerInfo);
Win32MajorVersion := OsVerInfo.dwMajorVersion;
Win32MinorVersion := OsVerInfo.dwMinorVersion;
Win32Platform := OsVerInfo.dwPlatformId;
if IsIconic(hWnd) then ShowWindow(hWnd, SW_RESTORE);
if GetForegroundWindow = hWnd then Result := True
else
begin
if ((Win32Platform = VER_PLATFORM_WIN32_NT) and (Win32MajorVersion > 4)) or
((Win32Platform = VER_PLATFORM_WIN32_WINDOWS) and ((Win32MajorVersion > 4)
or ((Win32MajorVersion = 4) and (Win32MinorVersion > 0)))) then
begin
Result := False;
ForegroundThreadID := GetWindowThreadProcessID(GetForegroundWindow, nil);
ThisThreadID := GetWindowThreadPRocessId(hWnd, nil);
if AttachThreadInput(ThisThreadID, ForegroundThreadID, True) then
begin
BringWindowToTop(hWnd);
SetForegroundWindow(hWnd);
AttachThreadInput(ThisThreadID, ForegroundThreadID, False);
Result := (GetForegroundWindow = hWnd);
end;
if not Result then
begin
SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, @Timeout, 0);
SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, nil,
SPIF_SENDCHANGE);
BringWindowToTop(hWnd);
SetForegroundWindow(hWnd);
SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, TObject(Timeout),
SPIF_SENDCHANGE);
end;
end
else
begin
BringWindowToTop(hWnd);
SetForegroundWindow(hWnd);
end;
Result := (GetForegroundWindow = hWnd);
end;
end; // End of function ForceForegroundWindow
← →
Anatoly Podgoretsky © (2010-04-06 16:37) [5]
> DVM © (06.04.10 15:57) [4]
Только, только начали избавляться от попрыгунчиков, так ты тут со своим кодом вылез.
← →
DVM © (2010-04-06 16:40) [6]
> Anatoly Podgoretsky © (06.04.10 16:37) [5]
Ну тут как ни крути это надо. Если надо переключать окна как панель задач.
← →
Anatoly Podgoretsky © (2010-04-06 16:51) [7]> DVM (06.04.2010 16:40:06) [6]
Мне за последствия страшно.
← →
Дмитрий С © (2010-04-07 03:00) [8]
> DVM © (06.04.10 15:57) [4]
Это сильно, конечно.
AttachThreadInput нужен для SetForegroundWindow?
> DVM © (06.04.10 15:55) [3]
Спасибо за код. Вопрос только:
Разве панель задач загружает иконку из ресурса exe файла, если из других мест достать не удалось?
> Leonid Troyanovsky © (06.04.10 11:34) [1]
Спасибо за ссылку, то что нужно. Сделал через EnumWindows, в таком случае своего окна не требуется вовсе.
Так, все-таки как штатно закрыть приложение, чтобы в случае чего, оно могло отобразить диалог (запрос на сохранение), послать WM_CLOSE или WM_SYSCOMMAND, SC_CLOSE? И как не штатно (тут думаю TerminateProcess)?
← →
Leonid Troyanovsky © (2010-04-07 10:34) [9]
> Дмитрий С © (07.04.10 03:00) [8]
> AttachThreadInput нужен для SetForegroundWindow?
Не нужен. Если SetForegroundWindow вызывается
при выполнении условий, описанных в msdn,
то фокус будет передан. Иначе, будет FlashWindow.
> Так, все-таки как штатно закрыть приложение, чтобы в случае
> чего, оно могло отобразить диалог (запрос на сохранение),
WM_SYSCOMMAND SC_CLOSE окну, чья кнопка на таскбаре, IMHO.
Только, наверное, SendMessageTimeout. У оного есть и флаг SMTO_ABORTIFHUNG. .
Ну, и TerminateProcess, на крайний случай.
--
Regards, LVT.
← →
DVM © (2010-04-07 12:13) [10]
> Дмитрий С © (07.04.10 03:00) [8]
> Разве панель задач загружает иконку из ресурса exe файла,
> если из других мест достать не удалось?
По моим наблюдениям, которые я проводил лет 7 назад - да.
> Дмитрий С © (07.04.10 03:00) [8]
> AttachThreadInput нужен для SetForegroundWindow?
http://codeguru.ru/windows/windows/common/%D0%BF%D0%B5%D1%80%D0%B5%D0%BC%D0%B5%D1%89%D0%B5%D0%BD%D0%B8%D0%B5-%D0%BE%D0%BA%D0%BD%D0%B0-%D0%BD%D0%B0-%D0%BF%D0%B5%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D0%B9-%D0%BF%D0%BB%D0%B0%D0%BD.html
← →
Anatoly Podgoretsky © (2010-04-07 14:42) [11]> DVM (07.04.2010 12:13:10) [10]
И даже наоборот, сначали из ресурса, а потом уж как нибудь.
Поэтому в вход в папку с тысячами файлов так медленен, извлекаются иконки и уж как следствие проверка антивирусом.
← →
Дмитрий С © (2010-04-07 14:45) [12]
> Anatoly Podgoretsky © (07.04.10 14:42) [11]
Причем тут это-то?
> По моим наблюдениям, которые я проводил лет 7 назад - да.
Кстати в Win7 при группировке кнопок панели задач, таскбар именно из ресурса иконку и берет.
> Leonid Troyanovsky © (07.04.10 10:34) [9]
Чуть позже продолжу разбираться и тестировать на КПК, подниму тему, если будут вопросы, пока вопросов нет, большое спасибо.
← →
Leonid Troyanovsky © (2010-04-07 15:44) [13]
> Дмитрий С © (07.04.10 14:45) [12]
> Чуть позже продолжу разбираться и тестировать на КПК, подниму
> тему, если будут вопросы,
А далее я - пас, там, наверное, какой-нить WinCE.
--
Regards, LVT.
Страницы: 1 вся ветка
Форум: "WinAPI";
Текущий архив: 2014.11.30;
Скачать: [xml.tar.bz2];
Память: 0.51 MB
Время: 0.003 c