551 lines
17 KiB
ObjectPascal
551 lines
17 KiB
ObjectPascal
{**************************************************************************************************}
|
|
{ }
|
|
{ Project JEDI Code Library (JCL) }
|
|
{ }
|
|
{ The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); }
|
|
{ you may not use this file except in compliance with the License. You may obtain a copy of the }
|
|
{ License at http://www.mozilla.org/MPL/ }
|
|
{ }
|
|
{ Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF }
|
|
{ ANY KIND, either express or implied. See the License for the specific language governing rights }
|
|
{ and limitations under the License. }
|
|
{ }
|
|
{ The Original Code is OpenDlgFavAdapter.pas. }
|
|
{ }
|
|
{ The Initial Developer of the Original Code is Petr Vones. }
|
|
{ Portions created by Petr Vones are Copyright (C) Petr Vones. All rights reserved. }
|
|
{ }
|
|
{ Contributor(s): }
|
|
{ Salvatore Besso }
|
|
{ }
|
|
{**************************************************************************************************}
|
|
{ }
|
|
{ Unit owner: Petr Vones }
|
|
{ }
|
|
{**************************************************************************************************}
|
|
|
|
// Last modified: $Date: 2005/12/26 18:03:41 $
|
|
// For history see end of file
|
|
|
|
unit OpenDlgFavAdapter;
|
|
|
|
interface
|
|
|
|
{$I jcl.inc}
|
|
|
|
uses
|
|
Windows, Messages, Classes, SysUtils, Controls, StdCtrls, ExtCtrls,
|
|
JclPeImage;
|
|
|
|
type
|
|
TFavOpenDialog = class (TObject)
|
|
private
|
|
FAddButton: TButton;
|
|
FDeleteMode: Boolean;
|
|
FDisableHelpButton: Boolean;
|
|
FDisablePlacesBar: Boolean;
|
|
FFavoriteComboBox: TComboBox;
|
|
FFavoriteFolders: TStrings;
|
|
FFavoritePanel: TPanel;
|
|
FHandle: HWND;
|
|
FHooks: TJclPeMapImgHooks;
|
|
FIsOpenPictDialog: Boolean;
|
|
FParentWnd: HWND;
|
|
FParentWndInstance: Pointer;
|
|
FOldParentWndInstance: Pointer;
|
|
FPictureDialogLastFolder: string;
|
|
FWndInstance: Pointer;
|
|
FOldWndInstance: Pointer;
|
|
FOnClose: TNotifyEvent;
|
|
FOnShow: TNotifyEvent;
|
|
procedure AddButtonClick(Sender: TObject);
|
|
procedure FavoriteComboBoxClick(Sender: TObject);
|
|
function GetCurrentFolder: string;
|
|
function GetFileNameEditWnd: HWND;
|
|
procedure SetCurrentFolder(const Value: string);
|
|
procedure SetDeleteMode(const Value: Boolean);
|
|
protected
|
|
procedure AdjustControlPos;
|
|
procedure DialogFolderChange;
|
|
procedure DialogShow;
|
|
procedure DoClose;
|
|
procedure DoShow;
|
|
procedure ParentWndProc(var Message: TMessage); virtual;
|
|
procedure WndProc(var Message: TMessage); virtual;
|
|
property CurrentFolder: string read GetCurrentFolder write SetCurrentFolder;
|
|
property DeleteMode: Boolean read FDeleteMode write SetDeleteMode;
|
|
property FileNameEditWnd: HWND read GetFileNameEditWnd;
|
|
public
|
|
constructor Create;
|
|
destructor Destroy; override;
|
|
procedure HookDialogs;
|
|
procedure LoadFavorites(const FileName: string);
|
|
procedure UnhookDialogs;
|
|
property DisableHelpButton: Boolean read FDisableHelpButton write FDisableHelpButton;
|
|
property DisablePlacesBar: Boolean read FDisablePlacesBar write FDisablePlacesBar;
|
|
property FavoriteFolders: TStrings read FFavoriteFolders;
|
|
property IsOpenPictDialog: Boolean read FIsOpenPictDialog;
|
|
property PictureDialogLastFolder: string read FPictureDialogLastFolder write FPictureDialogLastFolder;
|
|
property OnClose: TNotifyEvent read FOnClose write FOnClose;
|
|
property OnShow: TNotifyEvent read FOnShow write FOnShow;
|
|
end;
|
|
|
|
function InitializeFavOpenDialog: TFavOpenDialog;
|
|
|
|
implementation
|
|
|
|
uses
|
|
{$IFNDEF RTL140_UP}
|
|
Forms,
|
|
{$ENDIF ~RTL140_UP}
|
|
CommDlg, Dlgs,
|
|
JclFileUtils, JclStrings, JclSysInfo, JclSysUtils,
|
|
JclOtaConsts, JclOtaResources, JclOtaUtils;
|
|
|
|
{$R FavDlg.res}
|
|
|
|
type
|
|
TGetOpenFileName = function (var OpenFile: TOpenFilename): Bool; stdcall;
|
|
|
|
var
|
|
OldGetOpenFileName: TGetOpenFileName;
|
|
OldGetSaveFileName: TGetOpenFileName;
|
|
OldExplorerHook: function(Wnd: HWND; Msg: UINT; wParam: WPARAM; lParam: LPARAM): UINT stdcall;
|
|
FavOpenDialog: TFavOpenDialog;
|
|
|
|
function NewExplorerHook(Wnd: HWnd; Msg: UINT; WParam: WPARAM; LParam: LPARAM): UINT; stdcall;
|
|
begin
|
|
Result := OldExplorerHook(Wnd, Msg, WParam, LParam);
|
|
if (Msg = WM_INITDIALOG) and Assigned(FavOpenDialog) then
|
|
begin
|
|
FavOpenDialog.FHandle := Wnd;
|
|
FavOpenDialog.FOldWndInstance := Pointer(SetWindowLong(Wnd, GWL_WNDPROC, Longint(FavOpenDialog.FWndInstance)));
|
|
CallWindowProc(FavOpenDialog.FWndInstance, Wnd, Msg, WParam, LParam);
|
|
end;
|
|
end;
|
|
|
|
procedure InitOpenFileStruct(var OpenFile: TOpenFilename);
|
|
var
|
|
InitDir: string;
|
|
begin
|
|
with OpenFile do
|
|
if Flags and OFN_EXPLORER <> 0 then
|
|
begin
|
|
if Assigned(FavOpenDialog) then
|
|
FavOpenDialog.FIsOpenPictDialog := False;
|
|
if Flags and OFN_ENABLETEMPLATE = 0 then
|
|
begin
|
|
OldExplorerHook := lpfnHook;
|
|
lpfnHook := NewExplorerHook;
|
|
lpTemplateName := FavDialogTemplateName;
|
|
hInstance := FindResourceHInstance(FindClassHInstance(TFavOpenDialog));
|
|
Flags := Flags or OFN_ENABLETEMPLATE;
|
|
if Assigned(FavOpenDialog) then
|
|
begin
|
|
if FavOpenDialog.DisableHelpButton then
|
|
Flags := Flags and (not OFN_SHOWHELP);
|
|
{$IFDEF DELPHI6_UP}
|
|
if FavOpenDialog.DisablePlacesBar and (lStructSize = SizeOf(TOpenFilename)) then
|
|
FlagsEx := FlagsEx or OFN_EX_NOPLACESBAR;
|
|
{$ENDIF DELPHI6_UP}
|
|
end;
|
|
end
|
|
else
|
|
if (StrIComp(lpTemplateName, OpenPictDialogTemplateName) = 0) and Assigned(FavOpenDialog) then
|
|
begin
|
|
FavOpenDialog.FIsOpenPictDialog := True;
|
|
OldExplorerHook := lpfnHook;
|
|
lpfnHook := NewExplorerHook;
|
|
InitDir := FavOpenDialog.PictureDialogLastFolder;
|
|
if DirectoryExists(InitDir) then
|
|
lpstrInitialDir := PChar(FavOpenDialog.PictureDialogLastFolder)
|
|
else
|
|
FavOpenDialog.PictureDialogLastFolder := '';
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function NewGetOpenFileName(var OpenFile: TOpenFilename): Bool; stdcall;
|
|
begin
|
|
InitOpenFileStruct(OpenFile);
|
|
Result := OldGetOpenFileName(OpenFile);
|
|
end;
|
|
|
|
function NewGetSaveFileName(var OpenFile: TOpenFilename): Bool; stdcall;
|
|
begin
|
|
InitOpenFileStruct(OpenFile);
|
|
Result := OldGetSaveFileName(OpenFile);
|
|
end;
|
|
|
|
function InitializeFavOpenDialog: TFavOpenDialog;
|
|
begin
|
|
if not Assigned(FavOpenDialog) then
|
|
FavOpenDialog := TFavOpenDialog.Create;
|
|
Result := FavOpenDialog;
|
|
end;
|
|
|
|
//=== { TFavOpenDialog } =====================================================
|
|
|
|
constructor TFavOpenDialog.Create;
|
|
begin
|
|
inherited Create;
|
|
FFavoriteFolders := TStringList.Create;
|
|
FHooks := TJclPeMapImgHooks.Create;
|
|
FParentWndInstance := MakeObjectInstance(ParentWndProc);
|
|
FWndInstance := MakeObjectInstance(WndProc);
|
|
FFavoritePanel := TPanel.Create(nil);
|
|
with FFavoritePanel do
|
|
begin
|
|
Name := 'FavoritePanel';
|
|
BevelOuter := bvNone;
|
|
Caption := '';
|
|
FullRepaint := False;
|
|
FFavoriteComboBox := TComboBox.Create(FFavoritePanel);
|
|
with FFavoriteComboBox do
|
|
begin
|
|
SetBounds(6, 14, 300, Height);
|
|
Style := csDropDownList;
|
|
Sorted := True;
|
|
OnClick := FavoriteComboBoxClick;
|
|
Parent := FFavoritePanel;
|
|
end;
|
|
with TStaticText.Create(FFavoritePanel) do
|
|
begin
|
|
AutoSize := False;
|
|
SetBounds(6, 0, 100, 14);
|
|
Caption := RsFavorites;
|
|
FocusControl := FFavoriteComboBox;
|
|
Parent := FFavoritePanel;
|
|
end;
|
|
FAddButton := TButton.Create(FFavoritePanel);
|
|
with FAddButton do
|
|
begin
|
|
SetBounds(333, 14, 75, 23);
|
|
Caption := RsAdd;
|
|
OnClick := AddButtonClick;
|
|
Parent := FFavoritePanel;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
destructor TFavOpenDialog.Destroy;
|
|
begin
|
|
UnhookDialogs;
|
|
FreeObjectInstance(FParentWndInstance);
|
|
FreeObjectInstance(FWndInstance);
|
|
FreeAndNil(FFavoritePanel);
|
|
FreeAndNil(FFavoriteFolders);
|
|
FreeAndNil(FHooks);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TFavOpenDialog.AddButtonClick(Sender: TObject);
|
|
var
|
|
I: Integer;
|
|
Path: string;
|
|
begin
|
|
if DeleteMode then
|
|
begin
|
|
I := FFavoriteComboBox.ItemIndex;
|
|
Path := FFavoriteComboBox.Items[I];
|
|
if MessageBox(FHandle, PChar(Format(RsDelConfirm, [Path])), PChar(RsConfirmation),
|
|
MB_YESNO or MB_ICONQUESTION or MB_DEFBUTTON2) = ID_YES then
|
|
begin
|
|
FFavoriteComboBox.Items.Delete(I);
|
|
DeleteMode := False;
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
Path := CurrentFolder;
|
|
I := FFavoriteComboBox.Items.IndexOf(Path);
|
|
if I = -1 then
|
|
begin
|
|
FFavoriteComboBox.Items.Add(Path);
|
|
I := FFavoriteComboBox.Items.IndexOf(Path);
|
|
FFavoriteComboBox.ItemIndex := I;
|
|
DeleteMode := True;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TFavOpenDialog.AdjustControlPos;
|
|
var
|
|
ParentRect, FileNameEditRect, OkButtonRect: TRect;
|
|
|
|
procedure GetDlgItemRect(ItemID: Integer; var R: TRect);
|
|
begin
|
|
GetWindowRect(GetDlgItem(FParentWnd, ItemID), R);
|
|
MapWindowPoints(0, FParentWnd, R, 2);
|
|
end;
|
|
|
|
begin
|
|
GetWindowRect(FParentWnd, ParentRect);
|
|
if GetDlgItem(FParentWnd, edt1) <> 0 then
|
|
GetDlgItemRect(edt1, FileNameEditRect)
|
|
else
|
|
GetDlgItemRect(cmb1, FileNameEditRect);
|
|
GetDlgItemRect(1, OkButtonRect);
|
|
|
|
// Salvatore Besso: Changes to avoid truncation of Add button. I don't know why, but debugging I
|
|
// have discovered that ParentRect.Right was equal to 1024, ie Screen.Width. I also can't figure
|
|
// out why I can't preserve original help button that disappears using this expert.
|
|
// As visible in the changes, favorite panel width is just left of the original button column.
|
|
|
|
if IsWin2k or IsWinXP then
|
|
FAddButton.Width := 65;
|
|
FFavoritePanel.Width := OkButtonRect.Left - 1;
|
|
FFavoriteComboBox.Width := FFavoritePanel.Width - FFavoriteComboBox.Left - FAddButton.Width - 16;
|
|
FAddButton.Left := FFavoriteComboBox.Width + 14;
|
|
end;
|
|
|
|
procedure TFavOpenDialog.DialogFolderChange;
|
|
var
|
|
Path: string;
|
|
begin
|
|
Path := CurrentFolder;
|
|
with FFavoriteComboBox do
|
|
begin
|
|
ItemIndex := Items.IndexOf(Path);
|
|
DeleteMode := (ItemIndex <> -1);
|
|
end;
|
|
end;
|
|
|
|
procedure TFavOpenDialog.DialogShow;
|
|
var
|
|
PreviewRect: TRect;
|
|
begin
|
|
FParentWnd := GetParent(FHandle);
|
|
if IsOpenPictDialog then
|
|
DoShow
|
|
else
|
|
begin
|
|
GetClientRect(FHandle, PreviewRect);
|
|
PreviewRect.Top := PreviewRect.Bottom - 43;
|
|
FFavoritePanel.BoundsRect := PreviewRect;
|
|
FFavoritePanel.ParentWindow := FHandle;
|
|
if IsWin2k or IsWinXP then
|
|
FOldParentWndInstance := Pointer(SetWindowLong(FParentWnd, GWL_WNDPROC, Longint(FParentWndInstance)));
|
|
AdjustControlPos;
|
|
try
|
|
DoShow;
|
|
finally
|
|
FFavoriteComboBox.Items.Assign(FavoriteFolders);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TFavOpenDialog.DoClose;
|
|
begin
|
|
if Assigned(FOnClose) then
|
|
FOnClose(Self);
|
|
end;
|
|
|
|
procedure TFavOpenDialog.DoShow;
|
|
begin
|
|
if Assigned(FOnShow) then
|
|
FOnShow(Self);
|
|
end;
|
|
|
|
procedure TFavOpenDialog.FavoriteComboBoxClick(Sender: TObject);
|
|
begin
|
|
with FFavoriteComboBox do
|
|
if ItemIndex <> - 1 then
|
|
CurrentFolder := FFavoriteComboBox.Items[ItemIndex];
|
|
end;
|
|
|
|
function TFavOpenDialog.GetCurrentFolder: string;
|
|
var
|
|
Path: array [0..MAX_PATH] of Char;
|
|
begin
|
|
SetString(Result, Path, SendMessage(FParentWnd, CDM_GETFOLDERPATH, SizeOf(Path), Integer(@Path)));
|
|
StrResetLength(Result);
|
|
end;
|
|
|
|
function TFavOpenDialog.GetFileNameEditWnd: HWND;
|
|
begin
|
|
Result := GetDlgItem(FParentWnd, edt1);
|
|
if Result = 0 then
|
|
Result := GetDlgItem(FParentWnd, cmb13);
|
|
end;
|
|
|
|
procedure TFavOpenDialog.HookDialogs;
|
|
procedure HookImportsForModule(ModuleBase: Pointer);
|
|
const
|
|
comdlg32 = 'comdlg32.dll';
|
|
begin
|
|
if ModuleBase <> nil then
|
|
begin
|
|
FHooks.HookImport(ModuleBase, comdlg32, 'GetOpenFileNameA', @NewGetOpenFileName, @OldGetOpenFileName);
|
|
FHooks.HookImport(ModuleBase, comdlg32, 'GetSaveFileNameA', @NewGetSaveFileName, @OldGetSaveFileName);
|
|
end;
|
|
end;
|
|
var
|
|
Pe: TJclPeImage;
|
|
I: Integer;
|
|
HookedModule: LongWord;
|
|
begin
|
|
{ TODO : Hook all loaded modules }
|
|
Pe := TJclPeImage.Create(True);
|
|
try
|
|
HookedModule := FindClassHInstance(ClassType);
|
|
Pe.AttachLoadedModule(HookedModule);
|
|
if Pe.StatusOK then
|
|
begin
|
|
HookImportsForModule(Pointer(HookedModule));
|
|
for I := 0 to Pe.ImportList.UniqueLibItemCount - 1 do
|
|
HookImportsForModule(Pointer(GetModuleHandle(PChar(Pe.ImportList.UniqueLibItems[I].FileName))));
|
|
end;
|
|
finally
|
|
Pe.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TFavOpenDialog.LoadFavorites(const FileName: string);
|
|
begin
|
|
if FileExists(FileName) then
|
|
FavoriteFolders.LoadFromFile(FileName)
|
|
else
|
|
FavoriteFolders.Clear;
|
|
end;
|
|
|
|
procedure TFavOpenDialog.ParentWndProc(var Message: TMessage);
|
|
begin
|
|
with Message do
|
|
begin
|
|
Result := CallWindowProc(FOldParentWndInstance, FParentWnd, Msg, WParam, LParam);
|
|
if Msg = WM_SIZE then
|
|
AdjustControlPos;
|
|
end;
|
|
end;
|
|
|
|
procedure TFavOpenDialog.SetCurrentFolder(const Value: string);
|
|
var
|
|
LastFocus: HWND;
|
|
FileNameBuffer: string;
|
|
begin
|
|
if (FParentWnd <> 0) and DirectoryExists(Value) then
|
|
begin
|
|
LastFocus := GetFocus;
|
|
FileNameBuffer := GetWindowCaption(FileNameEditWnd);
|
|
SendMessage(FParentWnd, CDM_SETCONTROLTEXT, edt1, LPARAM(PChar(Value)));
|
|
SendMessage(GetDlgItem(FParentWnd, 1), BM_CLICK, 0, 0);
|
|
SendMessage(FParentWnd, CDM_SETCONTROLTEXT, edt1, LPARAM(PChar(FileNameBuffer)));
|
|
SetFocus(LastFocus);
|
|
end;
|
|
end;
|
|
|
|
procedure TFavOpenDialog.SetDeleteMode(const Value: Boolean);
|
|
begin
|
|
if FDeleteMode <> Value then
|
|
begin
|
|
FDeleteMode := Value;
|
|
if FDeleteMode then
|
|
FAddButton.Caption := RsDelete
|
|
else
|
|
FAddButton.Caption := RsAdd;
|
|
FFavoriteComboBox.Invalidate;
|
|
end;
|
|
end;
|
|
|
|
procedure TFavOpenDialog.UnhookDialogs;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
I := 0;
|
|
while I < FHooks.Count do
|
|
if not FHooks[I].Unhook then
|
|
Inc(I);
|
|
end;
|
|
|
|
procedure TFavOpenDialog.WndProc(var Message: TMessage);
|
|
|
|
procedure Default;
|
|
begin
|
|
with Message do
|
|
Result := CallWindowProc(FOldWndInstance, FHandle, Msg, WParam, LParam);
|
|
end;
|
|
|
|
begin
|
|
if FHandle <> 0 then
|
|
begin
|
|
case Message.Msg of
|
|
WM_NOTIFY:
|
|
begin
|
|
case (POFNotify(Message.LParam)^.hdr.code) of
|
|
CDN_INITDONE:
|
|
DialogShow;
|
|
CDN_FOLDERCHANGE:
|
|
if not IsOpenPictDialog then
|
|
DialogFolderChange;
|
|
CDN_FILEOK:
|
|
if IsOpenPictDialog then
|
|
FPictureDialogLastFolder := CurrentFolder;
|
|
end;
|
|
Default;
|
|
end;
|
|
WM_DESTROY:
|
|
begin
|
|
if not IsOpenPictDialog then
|
|
FavoriteFolders.Assign(FFavoriteComboBox.Items);
|
|
try
|
|
DoClose;
|
|
Default;
|
|
finally
|
|
if not IsOpenPictDialog then
|
|
FFavoritePanel.ParentWindow := 0;
|
|
FParentWnd := 0;
|
|
end;
|
|
end;
|
|
WM_NCDESTROY:
|
|
begin
|
|
Default;
|
|
FHandle := 0;
|
|
end;
|
|
else
|
|
Default;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
initialization
|
|
|
|
finalization
|
|
|
|
try
|
|
FreeAndNil(FavOpenDialog);
|
|
except
|
|
on ExceptionObj: TObject do
|
|
begin
|
|
JclExpertShowExceptionDialog(ExceptionObj);
|
|
raise;
|
|
end;
|
|
end;
|
|
|
|
|
|
// History:
|
|
|
|
// $Log: OpenDlgFavAdapter.pas,v $
|
|
// Revision 1.4 2005/12/26 18:03:41 outchy
|
|
// Enhanced bds support (including C#1 and D8)
|
|
// Introduction of dll experts
|
|
// Project types in templates
|
|
//
|
|
// Revision 1.3 2005/12/16 23:46:25 outchy
|
|
// Added expert stack form.
|
|
// Added code to display call stack on expert exception.
|
|
// Fixed package extension for D2006.
|
|
//
|
|
// Revision 1.2 2005/10/21 12:24:41 marquardt
|
|
// experts reorganized with new directory common
|
|
//
|
|
// Revision 1.1 2005/10/03 16:27:37 rrossmair
|
|
// - moved over from jcl\examples\vcl\idefavopendialogs
|
|
//
|
|
// Revision 1.5 2005/02/26 17:36:01 rrossmair
|
|
// - applied Salvatore Besso's fix for truncation of Add button when using large fonts.
|
|
// - some cleaning, module header updated.
|
|
//
|
|
|
|
end.
|