Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2014.11.30;
Скачать: CL | DM;

Вниз

Список запущенных приложений (тот что на панели задач).   Найти похожие ветки 

 
Дмитрий С ©   (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 вся ветка

Текущий архив: 2014.11.30;
Скачать: CL | DM;

Наверх




Память: 0.53 MB
Время: 0.005 c
2-1385473851
sas9568635
2013-11-26 17:50
2014.11.30
Dll-модули


15-1397939403
Юрий
2014-04-20 00:30
2014.11.30
С днем рождения ! 20 апреля 2014 воскресенье


11-1255323804
Soloton
2009-10-12 09:03
2014.11.30
Способ(ы) передачи сообщений от главного потока к второстепенным


15-1397651154
Дмитрий СС
2014-04-16 16:25
2014.11.30
Флешка как CD-ROM


15-1397720688
ТНЕ картман
2014-04-17 11:44
2014.11.30
голосование))