Delphi를 사용하여 Windows 셸 확장 작성
운영 체제의 원리에 익숙한 친구들은 완전한 운영 체제가 일반 사용자에게 편의를 제공하는 쉘을 제공한다는 것을 알 것입니다.
운영체제에서 제공하는 다양한 기능을 활용해보세요. Windows 셸(여기서는 Windows 95, Windows NT4.0 이상의 운영 체제를 나타냄)은 다음과 같은 기능을 제공할 뿐만 아니라
편리하고 아름다운 GUI 그래픽 인터페이스를 제공할 뿐만 아니라, 많은 소프트웨어에서 이러한 쉘 확장을 볼 수 있는 강력한 쉘 확장 기능도 제공합니다. 예를 들어
Winzip이 시스템에 설치되어 있는 경우 Windows 탐색기에서 폴더나 파일을 마우스 오른쪽 버튼으로 클릭하면 Winzip 파일이 팝업 메뉴에 나타납니다.
단축메뉴. 또는 Bullet FTP의 Windows 탐색기에 나타나는 FTP 사이트 폴더입니다.
Windows는 7가지 유형의 셸 확장(처리기라고 함)을 지원하며 해당 기능은 다음과 같이 간략하게 설명됩니다.
(1) 상황에 맞는 메뉴 처리기: 특정 유형의 파일 개체에 상황에 맞는 메뉴를 추가합니다.
(2) 끌어서 놓기 처리기는 사용자가 특정 유형의 파일 개체에 대해 끌어서 놓기 작업을 수행할 때 OLE 데이터 전송을 지원하는 데 사용됩니다.
(3) 아이콘 핸들러는 특정 파일 객체에 고유한 아이콘을 제공하는 데 사용되며 특정 유형의 파일 객체에 대한 아이콘을 지정할 수도 있습니다.
(4) PRerty 시트 핸들러는 파일 객체에 속성 페이지를 추가합니다. 즉, 파일 객체나 폴더 객체를 마우스 오른쪽 버튼으로 클릭하고 팝업 메뉴에서 속성을 선택합니다.
항목 뒤에 나타나는 대화 상자), 속성 페이지는 동일한 유형의 파일 개체에서 공유할 수 있거나 고유한 속성 페이지를 파일 개체에 할당할 수 있습니다.
(5) Windows를 통해 폴더 개체 또는 프린터 개체가 복사, 이동, 삭제 또는 이름 변경되면 시스템에서 복사 후크 처리기를 호출합니다.
특정 작업을 허용하거나 금지하려면 카피후크 핸들러를 추가하세요.
(6) 놓기 대상 핸들러는 객체를 다른 객체로 드래그 앤 드롭할 때 시스템에 의해 호출됩니다.
(7) 파일을 드래그, 드롭, 복사 또는 붙여넣을 때 시스템에서 데이터 개체 핸들러를 호출합니다.
Windows의 모든 셸 확장은 COM(Component Object Model) 구성 요소 모델을 기반으로 하며 셸은 인터페이스를 통해 개체에 액세스합니다.
셸 확장은 32비트 프로세스 내 서버 프로그램으로 설계되었으며 동적 링크 라이브러리 형태로 운영 체제에 서비스를 제공합니다. 그러므로 Windows를 사용하고 싶다면
사용자 인터페이스가 확장되면 COM 개체 작성에 대한 지식이 매우 필요합니다. 공간 제한으로 인해 독자는 여기서 COM을 소개하지 않습니다.
Microsoft의 MSDN 라이브러리 또는 관련 도움말 문서에 따르면 인터페이스는 개체를 작동하는 데 사용할 수 있는 일련의 기능과 프로시저를 포함하는 특수 클래스로 간주할 수 있습니다.
셸 확장을 작성한 후 적용하려면 등록해야 합니다. 모든 셸 확장은 Windows 레지스트리의 HKEY_CLASSES_ROOTCLSID 키 아래에 있어야 합니다.
아래에서 등록하세요. 이 키 아래에서 {0000002F-0000-0000-C000-000000000046}과 같은 이름을 가진 많은 키를 찾을 수 있습니다. 이러한 키는 전역적으로 고유한 클래스 식별자입니다.
가이드. 모든 셸 확장에는 전역적으로 고유한 클래스 식별자가 있어야 하며, 이는 Windows가 셸 확장 처리기를 찾는 방법입니다.
시스템의 셸 확장 동적 링크 라이브러리 위치는 클래스 식별자 아래 InProcServer32 하위 키에 기록됩니다. 파일 형식과 관련된 셸 확장자는 다음에 등록됩니다.
해당 유형의 shellex 기본 키 아래에 있습니다. Windows 운영 체제가 Windows NT인 경우 셸 확장도 레지스트리에 있어야 합니다.
기본 키 HKEY_LOCAL_MACHINESoftwareMicrosoftWindowsCurrentVersionShellExtensionsApproved로 등록합니다.
쉘 확장 DLL 프로그램을 컴파일한 후, Windows 자체에서 제공하는 regsvr32.exe를 이용하여 DLL 서버 프로그램을 등록할 수 있습니다. Delphi를 사용하는 경우 다음도 가능합니다.
등록하려면 실행 메뉴에서 ActiveX 서버 등록을 선택하세요.
먼저 Windows에서 파일이나 폴더를 마우스 오른쪽 버튼으로 클릭하면 나타나는 상황에 맞는 메뉴인 보다 일반적으로 사용되는 셸 확장 응용 프로그램을 소개하겠습니다.
이 메뉴를 상황에 맞는 메뉴라고 합니다. 상황에 맞는 메뉴에 메뉴 항목을 동적으로 추가하려면 상황에 맞는 메뉴 처리기를 작성할 수 있습니다. 예를 들어, 모든 사람
WinZip 및 UltraEdit과 같은 익숙한 소프트웨어는 컨텍스트 메뉴 처리기를 작성하여 메뉴 항목을 메뉴에 동적으로 추가합니다. 시스템에 설치된 경우
WinZip을 사용하고 Windows라는 파일(폴더)을 마우스 오른쪽 버튼으로 클릭하면 상황에 맞는 메뉴에 Windows.zip에 추가라는 메뉴 항목이 표시됩니다.
본 글에서 구현하고자 하는 Context Menu Handler는 WinZip에서 제공하는 Context Menu Handler와 유사하다. 그것은 추가됩니다
파일 작업 메뉴 항목. 이 항목을 클릭하면 인터페이스 프로그램이 파일 복사, 이동 등의 작업을 수행하는 파일 작업 창을 띄웁니다.
컨텍스트 메뉴 처리기를 작성하려면 IShellExtInit, IContextMenu 및 TComObjectFactory의 세 가지 인터페이스를 구현해야 합니다. IShellExtInit 구현
인터페이스 초기화, IContextMenu 인터페이스 개체는 상황에 맞는 메뉴를 구현하고 IComObjectFactory 인터페이스는 개체 생성을 구현합니다.
구체적인 프로그램 구현은 아래에 소개되어 있습니다. 먼저 델파이 메뉴의 File|New 항목을 클릭하고, New Item 창에서 DLL을 선택하여 DLL 프로젝트 파일을 생성합니다.
그런 다음 메뉴의 File|New 항목을 클릭하고 New Item 창에서 Unit을 선택하여 Unit 파일을 생성한 다음 메뉴의 File|New 항목을 클릭하고 New Item 창에서 Unit을 선택합니다.
양식을 선택하여 새 창을 만듭니다. 프로젝트 파일을 Contextmenu.dpr로, Unit1을 Contextmenuhandle.pas로 저장하고 양식을 다음으로 저장합니다.
OpWindow.pas.
Contextmenu.dpr의 프로그램 목록은 다음과 같습니다.
라이브러리 컨텍스트 메뉴;
용도
ComServ,
'contextmenuhandle.pas'에 있는 contextmenuhandle,
'opwindow.pas' {Form2}의 opwindow;
수출
DllGetClass객체,
DllCanUnloadNow,
DllRegisterServer,
DllUnregisterServer;
{$R *.TLB}
{$R *.RES}
시작하다
끝.
Contextmenuhandle의 프로그램 목록은 다음과 같습니다.
유닛 ContextMenuHandle;
인터페이스
Windows,ActiveX,ComObj,ShlObj,Classes를 사용합니다.
유형
TContextMenu = 클래스(TComObject,IShellExtInit,IContextMenu)
사적인
FFileName: Char의 배열[0..MAX_PATH];
보호됨
function IShellExtInit.Initialize = SEIInitialize; // 컴파일러 경고 방지
함수 SEIInitialize(pidlFolder: PItemIDList; lpdobj: IDataObject;
hKeyProgID: HKEY): HResult;
함수 QueryContextMenu(메뉴: HMENU; indexMenu, idCmdFirst, idCmdLast,
uFlags: UINT): HResult;
함수 InvokeCommand(var lpici: TCMInvokeCommandInfo): HResult;
함수 GetCommandString(idCmd, uType: UINT; pwReserved: PUINT;
pszName: LPSTR: cchMax: UINT): HResult;
끝;
const
Class_ContextMenu: TGUID = '{19741013-C829-11D1-8233-0020AF3E97A0}';
{GUID(Globally Unique Identifier)는 인터페이스를 고유하게 식별하는 16바이트(128바이트) 값입니다.}
var
파일목록:TStringList;
구현
ComServ, SysUtils, ShellApi, Registry,UnitForm을 사용합니다.
함수 TContextMenu.SEIInitialize(pidlFolder: PItemIDList; lpdobj: IDataObject;
hKeyProgID: HKEY): HResult;
var
StgMedium: TStgMedium;
FormatEtc: TFormatEtc;
파일번호,i:정수;
시작하다
file://lpdobj가 Nil과 같으면 이 호출은 실패합니다.
if (lpdobj = nil) 다음 시작
결과 := E_INVALIDARG;
출구;
끝;
file://은 먼저 FileList를 초기화하고 지워서 파일을 추가합니다.
파일목록:=TStringList.Create;
파일목록.지우기;
file://클립보드 형식 파일 초기화
FormatEtc로 시작하세요
cfFormat := CF_HDROP;
ptd := 없음;
dwaspect := DVASPECT_CONTENT;
린덱스 := -1;
tymed := TYMED_HGLOBAL;
끝;
결과 := lpdobj.GetData(FormatEtc, StgMedium);
실패(결과)이면 종료합니다.
file://먼저 사용자가 선택한 파일 개수를 조회합니다.
FileNumber := DragQueryFile(StgMedium.hGlobal,$FFFFFFFF,nil,0);
file://은 루프에서 읽고 사용자가 선택한 모든 파일을 FileList에 저장합니다.
i:=0에서 FileNumber-1까지 시작됩니다.
DragQueryFile(StgMedium.hGlobal, i, FFileName, SizeOf(FFileName));
FileList.Add(F파일이름);
결과 := NOERROR;
끝;
ReleaseStgMedium(StgMedium);
끝;
함수 TContextMenu.QueryContextMenu(메뉴: HMENU; indexMenu, idCmdFirst,
idCmdLast, uFlags: UINT): HResult;
시작하다
결과 := 0;
if ((uFlags 및 $0000000F) = CMF_NORMAL) 또는
((uFlags 및 CMF_EXPLORE) <> 0) 그런 다음 시작합니다.
//컨텍스트 메뉴에 메뉴 항목을 추가합니다. 메뉴 항목의 제목은 비트맵 파일 보기입니다.
InsertMenu(메뉴, indexMenu, MF_STRING 또는 MF_BYPOSITION, idCmdFirst,
PChar('파일 연산'));
// 추가된 메뉴 항목 수를 반환합니다.
결과 := 1;
끝;
끝;
함수 TContextMenu.InvokeCommand(var lpici: TCMInvokeCommandInfo): HResult;
var
frmOP:TForm1;
시작하다
// 먼저 프로세스가 프로그램이 아닌 시스템에 의해 호출되는지 확인하십시오.
if (HiWord(Integer(lpici.lpVerb)) <> 0) then
시작하다
결과 := E_FAIL;
출구;
끝;
// 전달된 매개변수의 유효성을 확인합니다.
if (LoWord(lpici.lpVerb) <> 0) 다음 시작
결과 := E_INVALIDARG;
출구;
끝;
file://파일 작업 창 생성
frmOP:=TForm1.Create(nil);
file://파일 작업 창의 목록에 모든 파일의 목록을 추가합니다.
frmOP.ListBox1.Items := 파일목록;
결과 := NOERROR;
끝;
함수 TContextMenu.GetCommandString(idCmd, uType: UINT; pwReserved: PUINT;
psz이름: LPSTR: cchMax: UINT): HRESULT;
시작하다
if (idCmd = 0) 다음 시작
if (uType = GCS_HELPTEXT) 그러면
{이 메뉴 항목의 도움말 정보를 반환합니다. 이 도움말 정보는 사용자가 마우스를 움직일 때 표시됩니다.
해당 메뉴 항목으로 이동 시 상태 표시줄에 나타납니다. }
StrCopy(pszName, PChar('이 메뉴 항목을 클릭하면 파일 작업이 수행됩니다.'));
결과 := NOERROR;
끝
또 다른
결과 := E_INVALIDARG;
끝;
유형
TContextMenuFactory = 클래스(TComObjectFactory)
공공의
절차 UpdateRegistry(등록: 부울);
끝;
절차 TContextMenuFactory.UpdateRegistry(Register: Boolean);
var
클래스ID: 문자열;
시작하다
등록한 다음 시작하면
상속된 UpdateRegistry(등록);
ClassID := GUIDToString(Class_ContextMenu);
file://확장 라이브러리 파일을 등록할 때 해당 라이브러리를 레지스트리에 추가합니다.
CreateRegKey('*shellex', ', ');
CreateRegKey('*shellexContextMenuHandlers', ', ');
CreateRegKey('*shellexContextMenuHandlersFileOpreation', ', ClassID);
file://운영 체제가 Windows NT인 경우
if (Win32Platform = VER_PLATFORM_WIN32_NT) 그러면
TRegistry.Create를 사용하여 수행
노력하다
루트키 := HKEY_LOCAL_MACHINE;
OpenKey('SOFTWAREMicrosoftWindowsCurrentVersionShell 확장', True);
OpenKey('승인됨', True);
WriteString(ClassID, '컨텍스트 메뉴 쉘 확장');
마지막으로
무료;
끝;
끝
그렇지 않으면 시작하다
DeleteRegKey('*shellexContextMenuHandlersFileOpreation');
상속된 UpdateRegistry(등록);
끝;
끝;
초기화
TContextMenuFactory.Create(ComServer, TContextMenu, Class_ContextMenu,
', '컨텍스트 메뉴 쉘 확장', ciMultiInstance,tmApartment);
끝.
OpWindow 창에 TListBox 컨트롤과 두 개의 TButton 컨트롤을 추가합니다. OpWindows.pas의 프로그램 목록은 다음과 같습니다.
유닛 opwindow;
인터페이스
용도
Windows, 메시지, SysUtils, 클래스, 그래픽, 컨트롤, 양식, 대화 상자,
ExtCtrls, StdCtrls,shlobj,shellapi,ActiveX;
유형
TForm1 = 클래스(TForm)
ListBox1: TListBox;
버튼1: T버튼;
Button2: T버튼;
절차 FormCreate(보내는 사람: TObject);
절차 FormClose(Sender: TObject; var Action: TCloseAction);
절차 Button1Click(Sender: TObject);
절차 Button2Click(보내는 사람: TObject);
사적인
{비공개 선언}
공공의
파일목록:TStringList;
{공개 선언}
끝;
var
Form1: TForm1;
구현
{$R *.DFM}
절차 TForm1.FormCreate(Sender: TObject);
시작하다
파일목록:=TStringList.Create;
Button1.Caption :='파일 복사';
Button2.Caption :='파일 이동';
셀프.쇼;
끝;
절차 TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
시작하다
파일목록.무료;
끝;
절차 TForm1.Button1Click(Sender: TObject);
var
sPath: 문자열;
fsTemp:SHFILEOPSTRUCT;
i:정수;
시작하다
sPath:=InputBox('파일 작업','입력 복사 경로','c:windows');
sPath<>'이면 시작
fsTemp.Wnd := Self.Handle;
file://파일 작업 유형 설정
fsTemp.wFunc :=FO_COPY;
file://은 실행 취소 작업을 허용합니다.
fsTemp.fFlags :=FOF_ALLOWUNDO;
i:=0에서 ListBox1.Items.Count-1까지 시작
file://소스 파일의 전체 경로 이름
fsTemp.pFrom := PChar(ListBox1.Items.Strings[i]);
file://복사할 경로
fsTemp.pTo := PChar(sPath);
fsTemp.lpszProgressTitle:='파일 복사';
SHFileOperation(fsTemp)<>0이면
ShowMessage('파일 복사 실패');
끝;
끝;
끝;
절차 TForm1.Button2Click(Sender: TObject);
var
sPath: 문자열;
fsTemp:SHFILEOPSTRUCT;
i:정수;
시작하다
sPath:=InputBox('파일 연산','이동 경로 입력','c:windows');
sPath<>'이면 시작
fsTemp.Wnd := Self.Handle;
fsTemp.wFunc :=FO_MOVE;
fsTemp.fFlags :=FOF_ALLOWUNDO;
i:=0에서 ListBox1.Items.Count-1까지 시작
fsTemp.pFrom := PChar(ListBox1.Items.Strings[i]);
fsTemp.pTo := PChar(sPath);
fsTemp.lpszProgressTitle:='파일 이동';
SHFileOperation(fsTemp)<>0이면
ShowMessage('파일 복사 실패');
끝;
끝;
끝;
끝.
메뉴에서 Project | Build ContextMenu 항목을 클릭하면 Delphi가 Contextmenu.dll 파일을 생성합니다.
Regsvr32.exe를 사용하여 프로그램을 등록한 다음 Windows 탐색기에서 하나 또는 여러 파일을 마우스 오른쪽 버튼으로 클릭하면 상황에 맞는 메뉴에 나타납니다.
파일 작업을 위한 추가 메뉴 항목이 있습니다. 이 항목을 클릭하면 선택한 모든 파일의 파일 이름이 팝업 창의 목록에 나열됩니다. 또는 파일 복사 버튼을 선택할 수 있습니다.
파일 이동 버튼은 파일 작업을 수행합니다.