How to prevent the use of the listview's popup menu in a TOpenDialog (Views: 100)


Using the TOpenDialog and TSaveDialog components you get the standard Windows dialog boxes including the ability to create/ delete files or folders. Is it possible to block the create/ delete options?


Well, few things are really impossible if you try hard enough, but this is at least somewhat difficult. The common dialog API has no facility to do this, the dialogs simply use the same listview class Explorer also uses, so it has all the same functionality. So to block these functions one would have to subclass (the API way) the listview control (to block right mouse clicks and the offending keyboard messages as well as WM_CONTEXTMENU). One could do that in the dialogs OnShow event. The problem is finding the handle of the listview, these Explorer-style dialogs have an utterly weird internal window hierarchy. And the listview in question has not been created yet when the OnShow event fires (go figure). So you have to post a user message to the form from the OnShow event and do the subclassing in that messages handler.

Here is a quick sketch of a modified opendialog class that prevents the use of the listviews popup menu. For some reason it is not possible to trap the DEL key press on the listview level, so if you want to also trap that, and perhaps even the editing of filenames, you will also need to subclass the shellview, which is the parent of the listview, and look for WM_NOTIFY messages from the listview there.

{ ...}
  TSafeOpenDialog = class(Dialogs.TOpenDialog)
    FOldListviewProc: Pointer;
    FListviewMethodInstance: Pointer;
    FLIstview: HWND;
    procedure WMApp(var msg: TMessage); message WM_APP;
    procedure DoShow; override;
    procedure ListviewWndProc(var msg: TMessage);
    destructor Destroy; override;

destructor TSafeOpenDialog.Destroy;
  if Assigned(FListviewMethodInstance) then

procedure TSafeOpenDialog.DoShow;
  PostMessage(handle, WM_APP, 0, 0);

procedure TSafeOpenDialog.ListviewWndProc(var msg: TMessage);
  msg.result := 0;
  case msg.Msg of
  msg.result := CallWindowProc(FOldListviewProc, FLIstview, msg.Msg,
    msg.WParam, msg.LParam);

procedure TSafeOpenDialog.WMApp(var msg: TMEssage);
  FListviewMethodInstance := MakeObjectInstance(ListviewWndProc);
  FListview := FindWindowEx(Windows.GetParent(handle), 0, 'SHELLDLL_DefView', nil);
  if FListview <> 0 then
    FListview := GetWindow(FListview, GW_CHILD);
    if FListview <> 0 then
      FOldListviewProc := Pointer(SetWindowLong(FListview, GWL_WNDPROC,
      OutputDebugString('Listview not found');
    OutputDebugString('Shell view not found');

<< Back to main page