; ; 资源管理器上下文菜单扩展 ; ;; Usage: ; To use it, you must build this source As a DLL And put the DLL in some known ; place (Not in C:\Windows\Temp Wink, so you remember where it is when you want ; To unregister it. ; ; But you must register it first, With this DOS command: ; C:\WINDOWS\system32>regsvr32 C:\PathToMyDLL\mydll.dll ; ; To unregister it: ; C:\WINDOWS\system32>regsvr32 /u C:\PathToMyDLL\mydll.dll ; ; ; Then launch an explorer window And right click on any file. The context menu ; should show a "View file name" item which, If selected, should show "Shows the ; file name" in the status bar. If clicked, a MessageRequester should appear With ; the name of the right-clicked file. ; Try compiling the dll with debugging support enabled, and you can track all ; object use with a debugger like DebugView (http://www.sysinternals.com/Utilities/DebugView.html) ; EnableCOMDebuggingGlobal ExistingObjectCount Global hModuleCOMClass(ShellMenuObject) COMInterface(ShellMenuObject, IClassFactory) COMInterface(ShellMenuObject, IShellExtInit) COMInterface(ShellMenuObject, IContextMenu)
COMConstructor(ShellMenuObject) ExistingObjectCount + 1 ; used to know if the dll can be unloaded COMConstructorReturn IClassFactory ; return IClassFactory from the constructor EndCOMConstructor
; ; 资源管理器上下文菜单扩展 ; ;; Usage: ; To use it, you must build this source As a DLL And put the DLL in some known ; place (Not in C:\Windows\Temp Wink, so you remember where it is when you want ; To unregister it. ; ; But you must register it first, With this DOS command: ; C:\WINDOWS\system32>regsvr32 C:\PathToMyDLL\mydll.dll ; ; To unregister it: ; C:\WINDOWS\system32>regsvr32 /u C:\PathToMyDLL\mydll.dll ; ; ; Then launch an explorer window And right click on any file. The context menu ; should show a "View file name" item which, If selected, should show "Shows the ; file name" in the status bar. If clicked, a MessageRequester should appear With ; the name of the right-clicked file. ; Try compiling the dll with debugging support enabled, and you can track all ; object use with a debugger like DebugView (http://www.sysinternals.com/Utilities/DebugView.html) ; EnableCOMDebuggingGlobal ExistingObjectCount Global hModuleCOMClass(ShellMenuObject) COMInterface(ShellMenuObject, IClassFactory) COMInterface(ShellMenuObject, IShellExtInit) COMInterface(ShellMenuObject, IContextMenu)
COMConstructor(ShellMenuObject) ExistingObjectCount + 1 ; used to know if the dll can be unloaded COMConstructorReturn IClassFactory ; return IClassFactory from the constructor EndCOMConstructor
; ; PropertyPage Shell Extension dll example ; Adds a new page to the properties displayed for drives in the explorer. ;; Usage: ; To use it, you must build this source As a DLL And put the DLL in some known ; place (Not in C:\Windows\Temp Wink, so you remember where it is when you want ; To unregister it. ; ; But you must register it first, With this DOS command: ; C:\WINDOWS\system32>regsvr32 C:\PathToMyDLL\mydll.dll ; ; To unregister it: ; C:\WINDOWS\system32>regsvr32 /u C:\PathToMyDLL\mydll.dll ; ; ; Then launch an explorer window And right click on a drive and select 'Properties' ; There should be an extra empty page in the Properties called "Example Property Page"; Try compiling the dll with debugging support enabled, and you can track all ; object use with a debugger like DebugView (http://www.sysinternals.com/Utilities/DebugView.html) ;; Compile the dll with com debugging support enabled, and you can track all ; object use with a debugger like DebugView (http://www.sysinternals.com/Utilities/DebugView.html) ; EnableCOMDebugging; for the unload function Global TotalObjectCount, DllInstanceCOMClass(PropertySheet) COMInterface(PropertySheet, IClassFactory) COMInterface(PropertySheet, IShellExtInit) COMInterface(PropertySheet, IShellPropSheetExt)
init\dwSize = SizeOf(INITCOMMONCONTROLSEX) init\dwICC = #ICC_DATE_CLASSES|#ICC_STANDARD_CLASSES InitCommonControlsEx_(@init) ; must call this to avoid a crash when loading the dialog box
; ; NOTE: maybe implement the CFSTR_MOUNTEDVOLUME format to handle NTFS volumes ; mounted on a directory and not a driveletter ;
Case #PSPCB_ADDREF: OutputDebugString_("Page is being added") ThisIUnknown\AddRef() ; prevent the dll/object from being destroyed while the page exists
Case #PSPCB_CREATE: OutputDebugString_("Dialog box is being created")
Case #PSPCB_RELEASE: OutputDebugString_("Page is being destroyed") ThisIUnknown\Release() ; allow release of the dll/object
Case #WM_INITDIALOG Case #WM_DESTROY Case #WM_NOTIFY *hdr.NMHDR = lParam OutputDebugString_("WM_NOTIFY: code = "+Str(*hdr\code))
If *hdr\code = #PSN_SETACTIVE DialogReturn(Window, 0) ; important to handle this, otherwise we get a crash! EndIf
EndSelect
ProcedureReturn #False EndProcedure; This is a dialog template for an empty dialog ; DataSection Dialog: Data.w 1 ; DlgVer Data.w $FFFF ; extended dlg structure Data.l 0 ; helpID Data.l 0 ; exStyle Data.l #WS_CHILD | #WS_VISIBLE ; Style Data.w 0 ; Nb of items in the dialog Data.w 0 ; x Data.w 0 ; y Data.w 0 ; w Data.w 0 ; h Data.w 0 ; PADDING Data.w $0000 ; NO menu! Data.w 0 ; PADDING Data.w $0000 ; No windowClass Data.w 0 ; PADDING Data.w $0000 ; NO title Data.w 0 ; PADDING
EndDataSection
; ; PropertyPage Shell Extension dll example ; Adds a new page to the properties displayed for drives in the explorer. ;; Usage: ; To use it, you must build this source As a DLL And put the DLL in some known ; place (Not in C:\Windows\Temp Wink, so you remember where it is when you want ; To unregister it. ; ; But you must register it first, With this DOS command: ; C:\WINDOWS\system32>regsvr32 C:\PathToMyDLL\mydll.dll ; ; To unregister it: ; C:\WINDOWS\system32>regsvr32 /u C:\PathToMyDLL\mydll.dll ; ; ; Then launch an explorer window And right click on a drive and select 'Properties' ; There should be an extra empty page in the Properties called "Example Property Page"; Try compiling the dll with debugging support enabled, and you can track all ; object use with a debugger like DebugView (http://www.sysinternals.com/Utilities/DebugView.html) ;; Compile the dll with com debugging support enabled, and you can track all ; object use with a debugger like DebugView (http://www.sysinternals.com/Utilities/DebugView.html) ; EnableCOMDebugging; for the unload function Global TotalObjectCount, DllInstanceCOMClass(PropertySheet) COMInterface(PropertySheet, IClassFactory) COMInterface(PropertySheet, IShellExtInit) COMInterface(PropertySheet, IShellPropSheetExt)
init\dwSize = SizeOf(INITCOMMONCONTROLSEX) init\dwICC = #ICC_DATE_CLASSES|#ICC_STANDARD_CLASSES InitCommonControlsEx_(@init) ; must call this to avoid a crash when loading the dialog box
; ; NOTE: maybe implement the CFSTR_MOUNTEDVOLUME format to handle NTFS volumes ; mounted on a directory and not a driveletter ;
Case #PSPCB_ADDREF: OutputDebugString_("Page is being added") ThisIUnknown\AddRef() ; prevent the dll/object from being destroyed while the page exists
Case #PSPCB_CREATE: OutputDebugString_("Dialog box is being created")
Case #PSPCB_RELEASE: OutputDebugString_("Page is being destroyed") ThisIUnknown\Release() ; allow release of the dll/object
; 资源管理器上下文菜单扩展
;
;; Usage:
; To use it, you must build this source As a DLL And put the DLL in some known
; place (Not in C:\Windows\Temp Wink, so you remember where it is when you want
; To unregister it.
;
; But you must register it first, With this DOS command:
; C:\WINDOWS\system32>regsvr32 C:\PathToMyDLL\mydll.dll
;
; To unregister it:
; C:\WINDOWS\system32>regsvr32 /u C:\PathToMyDLL\mydll.dll
;
;
; Then launch an explorer window And right click on any file. The context menu
; should show a "View file name" item which, If selected, should show "Shows the
; file name" in the status bar. If clicked, a MessageRequester should appear With
; the name of the right-clicked file. ; Try compiling the dll with debugging support enabled, and you can track all
; object use with a debugger like DebugView (http://www.sysinternals.com/Utilities/DebugView.html)
;
EnableCOMDebuggingGlobal ExistingObjectCount
Global hModuleCOMClass(ShellMenuObject)
COMInterface(ShellMenuObject, IClassFactory)
COMInterface(ShellMenuObject, IShellExtInit)
COMInterface(ShellMenuObject, IContextMenu)
COMClassData(ShellMenuObject)
nLockCount.l
m_pDataObj.IDataObject
File$
EndCOMClassData
COMConstructor(ShellMenuObject)
ExistingObjectCount + 1 ; used to know if the dll can be unloaded
COMConstructorReturn IClassFactory ; return IClassFactory from the constructor
EndCOMConstructor
COMDestructor(ShellMenuObject)
ExistingObjectCount - 1
EndCOMDestructor
EndCOMClass(ShellMenuObject, IClassFactory, IShellExtInit, IContextMenu)DefineCLSID(CLSID_ContextMenuHandler, $851aab5c, $2008, $4157, $9c, $5d, $a2, $8d, $fa, $7b, $26, $60)Procedure Error(message$)
wError = GetLastError_()
If wError
*ErrorBuffer = AllocateMemory(1024)
FormatMessage_(#FORMAT_MESSAGE_FROM_SYSTEM, 0, wError, 0, *ErrorBuffer, 1024, 0)
message$+Chr(10)+PeekS(*ErrorBuffer)
FreeMemory(*ErrorBuffer)
EndIf
MessageRequester("Error", message$)
EndProcedureProcedure Ansi2Uni(*st, *Buffer, blen)
If Len(PeekS(*st))<blen
ProcedureReturn MultiByteToWideChar_(#CP_ACP, 0, *st, -1, *Buffer, blen)
Else
ProcedureReturn 0
EndIf
EndProcedure
#CMF_DEFAULTONLY = 1Enumeration
#GCS_VERBA
#GCS_HELPTEXTA
#GCS_VALIDATEA
#GCS_VERBW
#GCS_HELPTEXTW
#GCS_VALIDATEW
EndEnumeration
#GCS_UNICODE = 4
#GCS_VERB = #GCS_VERBA
#GCS_HELPTEXT = #GCS_HELPTEXTA
#GCS_VALIDATE = #GCS_VALIDATEAStructure CMINVOKECOMMANDINFO
cbSize.l
fMask.l
hwnd.l
lpVerb.l
lpParameters.l
lpDirectory.l
nShow.l
dwHotKey.l
hIcon.l
EndStructureStructure CMINVOKECOMMANDINFOEX Extends CMINVOKECOMMANDINFO
lpTitle.l
lpVerbW.l
lpParametersW.l
lpDirectoryW.l
lpTitleW.l
ptInvoke.POINT
EndStructure#SEE_MASK_UNICODE = $4000
#CMIC_MASK_UNICODE = #SEE_MASK_UNICODE#SELFREG_E_FIRST = $80009E40
#SELFREG_E_CLASS = #SELFREG_E_FIRST+1#GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS = 4
Procedure ShellMenuObject_IClassFactory_CreateInstance(*THIS.ShellMenuObject, *pUnkOuter.IUnknown, *riid.GUID, *ppvObject) COMMethodOf(ShellMenuObject)
If *pUnkOuter
ProcedureReturn #CLASS_E_NOAGGREGATION
Else
IUnknown.IUnknown = *THIS
ProcedureReturn IUnknown\QueryInterface(*riid, *ppvObject)
EndIf
ProcedureReturn hr
EndProcedure
; Procedure ShellMenuObject_IClassFactory_LockServer(*THIS.ShellMenuObject, fLock) MethodOf(ShellMenuObject)
; ProcedureReturn #E_FAIL
; EndProcedure; The above empty method can be implemented with this single macro:
;
COMEmptyMethod(ShellMenuObject, IClassFactory, LockServer, #E_FAIL)
; 资源管理器上下文菜单扩展
;
;; Usage:
; To use it, you must build this source As a DLL And put the DLL in some known
; place (Not in C:\Windows\Temp Wink, so you remember where it is when you want
; To unregister it.
;
; But you must register it first, With this DOS command:
; C:\WINDOWS\system32>regsvr32 C:\PathToMyDLL\mydll.dll
;
; To unregister it:
; C:\WINDOWS\system32>regsvr32 /u C:\PathToMyDLL\mydll.dll
;
;
; Then launch an explorer window And right click on any file. The context menu
; should show a "View file name" item which, If selected, should show "Shows the
; file name" in the status bar. If clicked, a MessageRequester should appear With
; the name of the right-clicked file. ; Try compiling the dll with debugging support enabled, and you can track all
; object use with a debugger like DebugView (http://www.sysinternals.com/Utilities/DebugView.html)
;
EnableCOMDebuggingGlobal ExistingObjectCount
Global hModuleCOMClass(ShellMenuObject)
COMInterface(ShellMenuObject, IClassFactory)
COMInterface(ShellMenuObject, IShellExtInit)
COMInterface(ShellMenuObject, IContextMenu)
COMClassData(ShellMenuObject)
nLockCount.l
m_pDataObj.IDataObject
File$
EndCOMClassData
COMConstructor(ShellMenuObject)
ExistingObjectCount + 1 ; used to know if the dll can be unloaded
COMConstructorReturn IClassFactory ; return IClassFactory from the constructor
EndCOMConstructor
COMDestructor(ShellMenuObject)
ExistingObjectCount - 1
EndCOMDestructor
EndCOMClass(ShellMenuObject, IClassFactory, IShellExtInit, IContextMenu)DefineCLSID(CLSID_ContextMenuHandler, $851aab5c, $2008, $4157, $9c, $5d, $a2, $8d, $fa, $7b, $26, $60)Procedure Error(message$)
wError = GetLastError_()
If wError
*ErrorBuffer = AllocateMemory(1024)
FormatMessage_(#FORMAT_MESSAGE_FROM_SYSTEM, 0, wError, 0, *ErrorBuffer, 1024, 0)
message$+Chr(10)+PeekS(*ErrorBuffer)
FreeMemory(*ErrorBuffer)
EndIf
MessageRequester("Error", message$)
EndProcedureProcedure Ansi2Uni(*st, *Buffer, blen)
If Len(PeekS(*st))<blen
ProcedureReturn MultiByteToWideChar_(#CP_ACP, 0, *st, -1, *Buffer, blen)
Else
ProcedureReturn 0
EndIf
EndProcedure
#CMF_DEFAULTONLY = 1Enumeration
#GCS_VERBA
#GCS_HELPTEXTA
#GCS_VALIDATEA
#GCS_VERBW
#GCS_HELPTEXTW
#GCS_VALIDATEW
EndEnumeration
#GCS_UNICODE = 4
#GCS_VERB = #GCS_VERBA
#GCS_HELPTEXT = #GCS_HELPTEXTA
#GCS_VALIDATE = #GCS_VALIDATEAStructure CMINVOKECOMMANDINFO
cbSize.l
fMask.l
hwnd.l
lpVerb.l
lpParameters.l
lpDirectory.l
nShow.l
dwHotKey.l
hIcon.l
EndStructureStructure CMINVOKECOMMANDINFOEX Extends CMINVOKECOMMANDINFO
lpTitle.l
lpVerbW.l
lpParametersW.l
lpDirectoryW.l
lpTitleW.l
ptInvoke.POINT
EndStructure#SEE_MASK_UNICODE = $4000
#CMIC_MASK_UNICODE = #SEE_MASK_UNICODE#SELFREG_E_FIRST = $80009E40
#SELFREG_E_CLASS = #SELFREG_E_FIRST+1#GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS = 4
Procedure ShellMenuObject_IClassFactory_CreateInstance(*THIS.ShellMenuObject, *pUnkOuter.IUnknown, *riid.GUID, *ppvObject) COMMethodOf(ShellMenuObject)
If *pUnkOuter
ProcedureReturn #CLASS_E_NOAGGREGATION
Else
IUnknown.IUnknown = *THIS
ProcedureReturn IUnknown\QueryInterface(*riid, *ppvObject)
EndIf
ProcedureReturn hr
EndProcedure
; Procedure ShellMenuObject_IClassFactory_LockServer(*THIS.ShellMenuObject, fLock) MethodOf(ShellMenuObject)
; ProcedureReturn #E_FAIL
; EndProcedure; The above empty method can be implemented with this single macro:
;
COMEmptyMethod(ShellMenuObject, IClassFactory, LockServer, #E_FAIL)
; PropertyPage Shell Extension dll example
; Adds a new page to the properties displayed for drives in the explorer.
;; Usage:
; To use it, you must build this source As a DLL And put the DLL in some known
; place (Not in C:\Windows\Temp Wink, so you remember where it is when you want
; To unregister it.
;
; But you must register it first, With this DOS command:
; C:\WINDOWS\system32>regsvr32 C:\PathToMyDLL\mydll.dll
;
; To unregister it:
; C:\WINDOWS\system32>regsvr32 /u C:\PathToMyDLL\mydll.dll
;
;
; Then launch an explorer window And right click on a drive and select 'Properties'
; There should be an extra empty page in the Properties called "Example Property Page"; Try compiling the dll with debugging support enabled, and you can track all
; object use with a debugger like DebugView (http://www.sysinternals.com/Utilities/DebugView.html)
;; Compile the dll with com debugging support enabled, and you can track all
; object use with a debugger like DebugView (http://www.sysinternals.com/Utilities/DebugView.html)
;
EnableCOMDebugging; for the unload function
Global TotalObjectCount, DllInstanceCOMClass(PropertySheet)
COMInterface(PropertySheet, IClassFactory)
COMInterface(PropertySheet, IShellExtInit)
COMInterface(PropertySheet, IShellPropSheetExt)
COMClassData(PropertySheet)
Directory$
Thread.l
EndCOMClassData
COMConstructor(PropertySheet)
TotalObjectCount + 1
COMConstructorReturn IClassFactory
EndCOMConstructor
COMDestructor(PropertySheet)
TotalObjectCount - 1
EndCOMDestructor
EndCOMClass(PropertySheet, IClassFactory, IShellExtInit, IShellPropSheetExt)
#CLSID_MyPropertySheet = "{3b3dccdc-8263-4c16-8405-e1d58d6a5a46}"
#MyPropertySheetName = "PBTestPropertySheet.1"DefineCLSID(CLSID_MyPropertySheet, $3b3dccdc, $8263, $4c16, $84, $05, $e1, $d5, $8d, $6a, $5a, $46);- Method definitions
;
Procedure PropertySheet_IClassFactory_CreateInstance(*THIS.PropertySheet, *pUnkOuter.IUnknown, *IID.GUID, *pObject.LONG) COMMethodOf(PropertySheet)
Protected i
Protected IUnknown.IUnknown = *THIS If *pUnkOuter
ProcedureReturn #CLASS_E_NOAGGREGATION
Else
ProcedureReturn IUnknown\QueryInterface(*IID, *pObject)
EndIf
EndProcedureCOMEmptyMethod(PropertySheet, IClassFactory, LockServer, #E_FAIL)Procedure PropertySheet_IShellExtInit_Initialize(*THIS.PropertySheet, *Folder.ITEMIDLIST, DataObject.IDataObject, hkeyProgID) COMMethodOf(PropertySheet)
Protected Format.FORMATETC, Medium.STGMEDIUM
Protected Result = #E_FAIL
Protected Count, Length
Protected init.INITCOMMONCONTROLSEX
init\dwSize = SizeOf(INITCOMMONCONTROLSEX)
init\dwICC = #ICC_DATE_CLASSES|#ICC_STANDARD_CLASSES
InitCommonControlsEx_(@init) ; must call this to avoid a crash when loading the dialog box
;
; NOTE: maybe implement the CFSTR_MOUNTEDVOLUME format to handle NTFS volumes
; mounted on a directory and not a driveletter
;
If DataObject
Format\cfFormat = #CF_HDROP
Format\ptd = #Null
Format\dwAspect = #DVASPECT_CONTENT
Format\lindex = -1
Format\tymed = #TYMED_HGLOBAL
If DataObject\GetData(@Format, @Medium) = #S_OK
Count = DragQueryFile_(Medium\hGlobal, $FFFFFFFF, #Null, 0)
If Count = 1
Length = DragQueryFile_(Medium\hGlobal, 0, #Null, 0)
*THIS\Directory$ = Space(Length)
DragQueryFile_(Medium\hGlobal, 0, @*THIS\Directory$, Length+1)
Result = #S_OK
EndIf ReleaseStgMedium_(@Medium)
EndIf
EndIf ProcedureReturn Result
EndProcedure
Procedure PropertySheetPageProc(hWnd, uMsg, *page.PROPSHEETPAGE)
Protected *THIS.PropertySheet = *page\lParam
Protected ThisIUnknown.IUnknown = *page\lParam Select uMsg
Case #PSPCB_ADDREF: OutputDebugString_("Page is being added")
ThisIUnknown\AddRef() ; prevent the dll/object from being destroyed while the page exists
Case #PSPCB_CREATE: OutputDebugString_("Dialog box is being created")
Case #PSPCB_RELEASE: OutputDebugString_("Page is being destroyed")
ThisIUnknown\Release() ; allow release of the dll/object
EndSelect ProcedureReturn #True
EndProcedureMacro DialogReturn(Window, Value)
SetWindowLong_(Window, #DWL_MSGRESULT, Value)
ProcedureReturn #True
EndMacro#NF_QUERY = 3
#NF_REQUERY = 4
#NFR_ANSI = 1
#NFR_UNICODE = 2Procedure PropertySheetDialogProc(Window, Message, wParam, lParam)
Protected *hdr.NMHDR Select Message
Case #WM_INITDIALOG Case #WM_DESTROY Case #WM_NOTIFY
*hdr.NMHDR = lParam
OutputDebugString_("WM_NOTIFY: code = "+Str(*hdr\code))
If *hdr\code = #PSN_SETACTIVE
DialogReturn(Window, 0) ; important to handle this, otherwise we get a crash!
EndIf
EndSelect
ProcedureReturn #False
EndProcedure; This is a dialog template for an empty dialog
;
DataSection Dialog:
Data.w 1 ; DlgVer
Data.w $FFFF ; extended dlg structure
Data.l 0 ; helpID
Data.l 0 ; exStyle
Data.l #WS_CHILD | #WS_VISIBLE ; Style
Data.w 0 ; Nb of items in the dialog
Data.w 0 ; x
Data.w 0 ; y
Data.w 0 ; w
Data.w 0 ; h
Data.w 0 ; PADDING
Data.w $0000 ; NO menu!
Data.w 0 ; PADDING
Data.w $0000 ; No windowClass
Data.w 0 ; PADDING
Data.w $0000 ; NO title
Data.w 0 ; PADDING
EndDataSection
; PropertyPage Shell Extension dll example
; Adds a new page to the properties displayed for drives in the explorer.
;; Usage:
; To use it, you must build this source As a DLL And put the DLL in some known
; place (Not in C:\Windows\Temp Wink, so you remember where it is when you want
; To unregister it.
;
; But you must register it first, With this DOS command:
; C:\WINDOWS\system32>regsvr32 C:\PathToMyDLL\mydll.dll
;
; To unregister it:
; C:\WINDOWS\system32>regsvr32 /u C:\PathToMyDLL\mydll.dll
;
;
; Then launch an explorer window And right click on a drive and select 'Properties'
; There should be an extra empty page in the Properties called "Example Property Page"; Try compiling the dll with debugging support enabled, and you can track all
; object use with a debugger like DebugView (http://www.sysinternals.com/Utilities/DebugView.html)
;; Compile the dll with com debugging support enabled, and you can track all
; object use with a debugger like DebugView (http://www.sysinternals.com/Utilities/DebugView.html)
;
EnableCOMDebugging; for the unload function
Global TotalObjectCount, DllInstanceCOMClass(PropertySheet)
COMInterface(PropertySheet, IClassFactory)
COMInterface(PropertySheet, IShellExtInit)
COMInterface(PropertySheet, IShellPropSheetExt)
COMClassData(PropertySheet)
Directory$
Thread.l
EndCOMClassData
COMConstructor(PropertySheet)
TotalObjectCount + 1
COMConstructorReturn IClassFactory
EndCOMConstructor
COMDestructor(PropertySheet)
TotalObjectCount - 1
EndCOMDestructor
EndCOMClass(PropertySheet, IClassFactory, IShellExtInit, IShellPropSheetExt)
#CLSID_MyPropertySheet = "{3b3dccdc-8263-4c16-8405-e1d58d6a5a46}"
#MyPropertySheetName = "PBTestPropertySheet.1"DefineCLSID(CLSID_MyPropertySheet, $3b3dccdc, $8263, $4c16, $84, $05, $e1, $d5, $8d, $6a, $5a, $46);- Method definitions
;
Procedure PropertySheet_IClassFactory_CreateInstance(*THIS.PropertySheet, *pUnkOuter.IUnknown, *IID.GUID, *pObject.LONG) COMMethodOf(PropertySheet)
Protected i
Protected IUnknown.IUnknown = *THIS If *pUnkOuter
ProcedureReturn #CLASS_E_NOAGGREGATION
Else
ProcedureReturn IUnknown\QueryInterface(*IID, *pObject)
EndIf
EndProcedureCOMEmptyMethod(PropertySheet, IClassFactory, LockServer, #E_FAIL)Procedure PropertySheet_IShellExtInit_Initialize(*THIS.PropertySheet, *Folder.ITEMIDLIST, DataObject.IDataObject, hkeyProgID) COMMethodOf(PropertySheet)
Protected Format.FORMATETC, Medium.STGMEDIUM
Protected Result = #E_FAIL
Protected Count, Length
Protected init.INITCOMMONCONTROLSEX
init\dwSize = SizeOf(INITCOMMONCONTROLSEX)
init\dwICC = #ICC_DATE_CLASSES|#ICC_STANDARD_CLASSES
InitCommonControlsEx_(@init) ; must call this to avoid a crash when loading the dialog box
;
; NOTE: maybe implement the CFSTR_MOUNTEDVOLUME format to handle NTFS volumes
; mounted on a directory and not a driveletter
;
If DataObject
Format\cfFormat = #CF_HDROP
Format\ptd = #Null
Format\dwAspect = #DVASPECT_CONTENT
Format\lindex = -1
Format\tymed = #TYMED_HGLOBAL
If DataObject\GetData(@Format, @Medium) = #S_OK
Count = DragQueryFile_(Medium\hGlobal, $FFFFFFFF, #Null, 0)
If Count = 1
Length = DragQueryFile_(Medium\hGlobal, 0, #Null, 0)
*THIS\Directory$ = Space(Length)
DragQueryFile_(Medium\hGlobal, 0, @*THIS\Directory$, Length+1)
Result = #S_OK
EndIf ReleaseStgMedium_(@Medium)
EndIf
EndIf ProcedureReturn Result
EndProcedure
Procedure PropertySheetPageProc(hWnd, uMsg, *page.PROPSHEETPAGE)
Protected *THIS.PropertySheet = *page\lParam
Protected ThisIUnknown.IUnknown = *page\lParam Select uMsg
Case #PSPCB_ADDREF: OutputDebugString_("Page is being added")
ThisIUnknown\AddRef() ; prevent the dll/object from being destroyed while the page exists
Case #PSPCB_CREATE: OutputDebugString_("Dialog box is being created")
Case #PSPCB_RELEASE: OutputDebugString_("Page is being destroyed")
ThisIUnknown\Release() ; allow release of the dll/object
EndSelect ProcedureReturn #True
EndProcedureMacro DialogReturn(Window, Value)
SetWindowLong_(Window, #DWL_MSGRESULT, Value)
ProcedureReturn #True
EndMacro#NF_QUERY = 3
#NF_REQUERY = 4
#NFR_ANSI = 1
#NFR_UNICODE = 2Procedure PropertySheetDialogProc(Window, Message, wParam, lParam)
Protected *hdr.NMHDR Select Message
Case #WM_INITDIALOG Case #WM_DESTROY Case #WM_NOTIFY
*hdr.NMHDR = lParam
OutputDebugString_("WM_NOTIFY: code = "+Str(*hdr\code))
If *hdr\code = #PSN_SETACTIVE
DialogReturn(Window, 0) ; important to handle this, otherwise we get a crash!
EndIf
EndSelect
ProcedureReturn #False
EndProcedure; This is a dialog template for an empty dialog
;
DataSection Dialog:
Data.w 1 ; DlgVer
Data.w $FFFF ; extended dlg structure
Data.l 0 ; helpID
Data.l 0 ; exStyle
Data.l #WS_CHILD | #WS_VISIBLE ; Style
Data.w 0 ; Nb of items in the dialog
Data.w 0 ; x
Data.w 0 ; y
Data.w 0 ; w
Data.w 0 ; h
Data.w 0 ; PADDING
Data.w $0000 ; NO menu!
Data.w 0 ; PADDING
Data.w $0000 ; No windowClass
Data.w 0 ; PADDING
Data.w $0000 ; NO title
Data.w 0 ; PADDING
EndDataSection