Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "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.002 c
15-1397751666
KilkennyCat
2014-04-17 20:21
2014.11.30
Как правильно сделать запрос SQL


15-1397823673
ВладОшин
2014-04-18 16:21
2014.11.30
напомните, как сплитер динамически поместить правильно


15-1398157909
Виктор1985
2014-04-22 13:11
2014.11.30
Трюки в Delphi


15-1398112205
Юрий
2014-04-22 00:30
2014.11.30
С днем рождения ! 22 апреля 2014 вторник


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





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский