Форум: "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 := "Ñâîéñòâà: " + 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.49 MB
Время: 0.042 c