Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "WinAPI";
Текущий архив: 2004.10.03;
Скачать: [xml.tar.bz2];

Вниз

Диалог свойств файла (ShellExecuteEx)   Найти похожие ветки 

 
R1   (2004-08-18 17:38) [0]

Написал элементарную программку для показа диалога свойств файла, переданного в командной строке:

program showprop;

uses
 ShellApi;

var
 ShellExecuteInfo: TShellExecuteInfo;
begin
 if ParamCount <> 1 then
   WriteLn("One and only parameter expected.")
 else
 begin
   FillChar(ShellExecuteInfo, SizeOf(ShellExecuteInfo), 0);
   ShellExecuteInfo.cbSize := SizeOf(ShellExecuteInfo);
   ShellExecuteInfo.lpFile := PChar(ParamStr(1));
   ShellExecuteInfo.lpVerb := "properties";
   ShellExecuteInfo.fMask := SEE_MASK_INVOKEIDLIST;
   ShellExecuteEx(@ShellExecuteInfo);
 end;
end.

Однако при запуске:
showprop.exe c:\autoexec.bat
результатов работы программки (диалога свойств файла autoexec.bat) не наблюдается.

После небольшой добавки, а именно вставки вызова MessageBox сразу после ShellExecuteEx(@ShellExecuteInfo):

program showprop;

uses
 ShellApi, Windows;

var
 ShellExecuteInfo: TShellExecuteInfo;
begin
 if ParamCount <> 1 then
   WriteLn("One and only parameter expected.")
 else
 begin
   FillChar(ShellExecuteInfo, SizeOf(ShellExecuteInfo), 0);
   ShellExecuteInfo.cbSize := SizeOf(ShellExecuteInfo);
   ShellExecuteInfo.lpFile := PChar(ParamStr(1));
   ShellExecuteInfo.lpVerb := "properties";
   ShellExecuteInfo.fMask := SEE_MASK_INVOKEIDLIST;
   ShellExecuteEx(@ShellExecuteInfo);
   MessageBox(0, "qwerty", "qwerty", MB_OK);
 end;
end.

желаемое окно свойств файла появляется, причем через некоторое время после (!) MessageBox"а. А после нажатия на ОК MessageBox"а окно свойств исчезает.

Что и как надо делать, чтобы вывести окно свойств файла (и только его) и чтобы оно не исчезало самопроизвольно, а только когда я сам его закрою?


 
simpson ©   (2004-08-18 18:20) [1]

Попробуй так:


unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls;

const
 SHOP_PRINTERNAME = 1;
 SHOP_FILEPATH = 2;
 SHOP_VOLUMEGUID = 4;

type
 TForm1 = class(TForm)
   Button1: TButton;
   Edit1: TEdit;
   procedure Button1Click(Sender: TObject);
   procedure FormCreate(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form1: TForm1;

function SHObjectProperties(hOwnerWnd: HWND; dwType: DWORD;
 szObject, szPage: PWideChar): LongBool; stdcall;

implementation

function SHObjectProperties(hOwnerWnd: HWND; dwType: DWORD;
 szObject, szPage: PWideChar): LongBool;
 external "shell32.dll" name "SHObjectProperties";

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
 S: WideString;
begin
 S := Edit1.Text;
 if not SHObjectProperties(Application.Handle, SHOP_FILEPATH, PWideChar(S), nil) then
   ShowMessage("sorry...");
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 Edit1.Text := ParamStr(0);
end;

end.


 
simpson ©   (2004-08-18 18:40) [2]

Извиняюсь... просмотрел, что приложение консольное.
Тогда все в порядке вещей - завершается приложение, закрывается окно свойств.


 
R1   (2004-08-18 20:02) [3]

Как говорится, "все в порядке, идем ко дну, т. капитан!" :)

Вот как раз и хочется, чтобы диалог свойств файла оставался, пока лично его не закроют.

Кстати, о SHObjectProperties... Это какая-то странная функция, вообще... Сначала была совсем уж недокументирована, начиная с 5-ой версии shell32.dll она документирована, но по имени не вызывается, только по ординалу 178... В общем, вариант:

program showprop;

function SHObjectProperties(hWnd: LongWord; dwType: LongWord; szObject: Pointer;
 szPage: Pointer): LongBool; external "shell32.dll" index 178;

const
 SHOP_FILEPATH = 2;

begin
 if ParamCount <> 1 then
   WriteLn("One and only parameter expected.")
 else
   SHObjectProperties(0, SHOP_FILEPATH, PChar(ParamStr(1)), nil);

   { // тот же результат, что и строчкой выше...
   SHObjectProperties(Windows.FindWindow("Progman", "Program Manager"),
     SHOP_FILEPATH, PChar(ParamStr(1)), nil);
   }
end.

показывает диалог свойств какого-то неизвестного мне тома винчестера (с заголовком "Свойства: Том без метки", неизвестной файловой системой и с нулевыми емкостями)... Сам процесс showprop.exe при этом работает (в смысле, висит - в хорошем смысле - в памяти), пока этот диалог не закроют.

Таки как вызвать диалог свойств файла, закрыться - и чтоб этот диалог потом остался?


 
R1   (2004-08-18 20:06) [4]

Оговорюсь - 1) на дуракоустойчивость пока забил, допустим, showprop.exe всегда вызывается с ровно одним параметром; 2) программа не обязательно консольная (на WriteLn просьба пристальное внимание не обращать :)).


 
nikkie ©   (2004-08-19 02:30) [5]

я посмотрел Spy++ - диалог принадлежит нашему процессу, просто создан он другим потоком. варианта вижу два - либо прицепиться к чужому процессу (идеально explorer.exe - и вызвать ShellExecute в его контексте), либо банально считать количество потоков при завершении программы и не выходить, пока их больше, чем 1.


 
R1   (2004-08-19 15:20) [6]

nikkie ©   (19.08.04 02:30) [5]

> прицепиться к чужому процессу (идеально explorer.exe - и вызвать ShellExecute в его контексте)

Прошу прощения за возможную наивность, но как это сделать - вызвать ShellExecuteEx в контексте другого процесса, в частности, explorer.exe?

Очередной вариант:

program showprop;

uses
 ShellApi, Windows;

var
 ShellExecuteInfo: TShellExecuteInfo;
 ParentProcessID: THandle;
begin
 if ParamCount = 1 then
 begin
   FillChar(ShellExecuteInfo, SizeOf(ShellExecuteInfo), 0);
   ShellExecuteInfo.cbSize := SizeOf(ShellExecuteInfo);
   ShellExecuteInfo.lpFile := PChar(ParamStr(1));
   ShellExecuteInfo.lpVerb := "properties";
   ShellExecuteInfo.fMask := SEE_MASK_INVOKEIDLIST;
   GetWindowThreadProcessId(FindWindow("TAppBuilder", "Delphi 5 - showprop"),
     @ParentProcessID);
   ShellExecuteInfo.hProcess := ParentProcessID;
   ShellExecuteEx(@ShellExecuteInfo);
   MessageBox(0, "qwerty", "qwerty", MB_OK);
 end; // else
end.

не канает с тем же результатом - окно свойств живет только до нажатия на ОК MessageBox"а...


 
nikkie ©   (2004-08-19 15:39) [7]

поищи по этому форуму - обсуждается периодически внедрение в чужой процесс. обычно к Рихтеру отсылают. я все варианты не скажу, только что вспоминается: AppInitDLL, глобальный хук, CreateRemoteThread на NT-системах. но городить это ради того, чтобы диалог не закрывался - овчинка выделки не стоит. другое дело, если твое приложение можно реализовать как shell extension dll, например. тогда уже автоматически в процессе explorer-a окажешься.


 
R1   (2004-08-20 17:02) [8]

Понятно. Овчинка, действительно, выделки не стоит.

Вопрос остается открытым: таки как показать диалог свойств файла, закрыться, а диалог чтобы остался? Ведь если в проводнике вызвать "Свойства", потом закрыть проводник - диалог-то остается...


 
nikkie ©   (2004-08-20 17:36) [9]

>Ведь если в проводнике вызвать "Свойства", потом закрыть проводник - диалог-то остается...
это ты не проводник закрываешь, а одно из его окошек.
попробуй explorer.exe через TaskManager снять.

Вопрос остается открытым
>банально считать количество потоков при завершении программы и не выходить, пока их больше, чем 1.


 
R1   (2004-08-20 20:01) [10]

1) У меня вообще explorer.exe отсутствует в диспетчере задач. У меня Aston. :) Но мысль понятна, все верно. Да, действительно, при снятии explorer.exe, все открытые в нем окна свойств закрываются. Так как же он их так запускает?

2) Возникает другой вопрос - а как узнать количество потоков, запущеных процессом?

Можно, конечно, узнать количество дескрипторов - GetProcessHandleCount - и на этом как-то основываться, но, может быть, я чего-то в хелпе не заметил и можно легко узнать количество потоков?

И потом... Мне кажется, это тоже не выход. Сейчас попытаюсь объяснить...

Очередной вариант:

program showprop;

uses
 ShellApi, Windows, SysUtils;

function WaitingThreadFunc(PropCaption: PChar): DWORD; stdcall;
begin
 while FindWindow("#32770 (Dialog)", PropCaption) <> 0 do
   ;
 Result := 0;
end;

var
 ShellExecuteInfo: TShellExecuteInfo;
 ThreadHandle: THandle;
 szCaption: PChar;
 ThreadID: DWORD;
 S: string;
begin
 if ParamCount = 1 then
 begin
   FillChar(ShellExecuteInfo, SizeOf(ShellExecuteInfo), 0);
   ShellExecuteInfo.cbSize := SizeOf(ShellExecuteInfo);
   ShellExecuteInfo.lpFile := PChar(ParamStr(1));
   ShellExecuteInfo.lpVerb := "properties";
   ShellExecuteInfo.fMask := SEE_MASK_INVOKEIDLIST;
   ShellExecuteEx(@ShellExecuteInfo);

   GetMem(szCaption, 80);
   S := "&#209;&#226;&#238;&#233;&#241;&#242;&#226;&#224;: " + ParamStr(1);
   StrCopy(szCaption, PChar(S));
   ThreadHandle := CreateThread(nil, 0, @WaitingThreadFunc,
     szCaption, 0 {CREATE_SUSPENDED}, ThreadID);
   //SetThreadPriority(ThreadHandle, THREAD_PRIORITY_IDLE);
   //ResumeThread(ThreadHandle);
   WaitForSingleObject(ThreadHandle, INFINITE);
   CloseHandle(ThreadHandle);
   FreeMem(szCaption);
 end;
end.

не проканал, т.к. на момент, когда поток (WaitingThreadFunc) получает управление, окно свойств еще не создано, и он честным образом тут же возвращает ноль - приложение закрывается, окна свойств я так и не увидел. (Если в потоке вместо FindWindow поставить MessageBox, то сначала появляется он, а уж после него - окно свойств файла.) Мне кажется, что вариант с подсчетом количества потоков отработает по той же схеме. Ну не создасться окно свойств, пока прога хоть чем-то занимается...

Все ж таки, всемогущий ALL - как показать окно свойств и чтоб оно не исчезло, пока его не закроют?

Может быть, запускать процесс explorer.exe с какими-нибудь параметрами?



Страницы: 1 вся ветка

Форум: "WinAPI";
Текущий архив: 2004.10.03;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.61 MB
Время: 0.08 c
3-1094024391
Koala
2004-09-01 11:39
2004.10.03
Клиент-сервер (MIDAS) под Firebird 1.5


14-1095200367
Marser
2004-09-15 02:19
2004.10.03
50 самых тупых запросов в Яndex-e


1-1094607254
Sollo
2004-09-08 05:34
2004.10.03
Импорт функций из sys файлов


14-1094389442
начинающий
2004-09-05 17:04
2004.10.03
Delphi vs. C++


1-1095326364
_PG_
2004-09-16 13:19
2004.10.03
Можно ли изменить ФОНТ заголовка окна?





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский