打开公用对话框的初始视图类型问题


终于找到了下面那几个常数的原始出处了:
http://vbnet.mvps.org/index.html?code/hooks/fileopensavedlghooklvview.htm
原来是一个叫 Brad Martinez 的高人发现的! 

他还告诉我们,这些常数以及 WM_COMMAND 的消息他都是使用 spy++ 发现的!所以,能够做到聪明的使用工具也是高手和普通人的区别之一,惭愧!下面是他代码中一部分:


  1. // These command IDs were obtained by spelunking the File Open dialog with Spy++.
  2. enum {
  3.     ODM_UNDEFINED   = 0,
  4.     ODM_VIEW_ICONS  = 0x7029,
  5.     ODM_VIEW_LIST   = 0x702b,
  6.     ODM_VIEW_DETAIL = 0x702c,
  7.     ODM_VIEW_THUMBS = 0x702d,
  8.     ODM_VIEW_TILES  = 0x702e,
  9. };
  10. //
  11. // This class is used to subclass the "SHELLDLL_DefView" window in the file
  12. // open dialog.
  13. //
  14. class CListViewShellWnd : public CWnd
  15. {
  16. public:
  17.     // These are the WM_COMMAND IDs to send to the shell window to set the
  18.     // different folder views. These were obtained using Spy++ to examine
  19.     // which messages are sent to the shell window.

 

=============================================================

 

不久前在回答关于“如何使打开对话框缺省显示缩略图”的问题时,我是使用模拟鼠标/键盘按键的方法来实现的(参见这里)。昨天,在浏览到 Carlos Alloatti 的网站 上时发现他新增了一个 ctl32_filedialog, ctl32_openfledialog 的类,他是使用 GetOpenFileName API 来调用 comdlg32 中的打开文件对话框;上一篇中我当时说过,要在打开公用对话框时指定视图的样式,只有 GetOpenFileNameEx 函数有此功能,但 MS 只在用于 WindowsMobile 5.0 的 API 函数库中导出了它,在用于 Windows 2K/XP/Vista 的系统中都无法使用!那 Carlos 又是怎样实现的呢?仔细分析了他的代码后发现,他使用了 vfp2c32 中的 CreateBackCallFunc 方法来创建一个回调函数,并放入 OPENFILENAME 结构中传给 GetOpenFileName API,然后在操作系统调用回调函数时找到对话框中的 SHELLDLL_DefView 窗口,发送 WM_COMMAND(???)消息给这个窗口,参数是: wParam 为要显示的视图类型,可用的视图类型常数定义如下:

#define SHVIEW_THUMBNAIL    0x702D
#define SHVIEW_TILE         0x702E
#define SHVIEW_ICON         0x7029
#define SHVIEW_LIST         0x702B
#define SHVIEW_REPORT       0x702C


他是如何得知可以用发送 WM_COMMAND 消息的方法,以及这几个常数来自何方就不得而知了!我在 msdn 中也没有看到过这种用法和常数定义,但此法确实可以做到更改视图类型。这样一来,原来的解决方法就可以改得更简单(不用再模拟鼠标/键盘操作了,发一条消息即可),并且更可靠一些(不用担心在模拟鼠标键盘操作时用户快速的移动鼠标来捣乱),基本思路还是用原来的,这样可以避免使用 vfp2c32.fll 外部库,更改后的代码如下:
这里我给这个表单加了一个 InitViewStyle 属性,你只要更改它为 SHVIEW_xxxx 中其他值就可以指定打开对话框的初始样式,你也可以很容易的将它改写为一个公用类,再提供一个 SetInitViewStyle 方法就可以指定打开对话框时的任意样式了。

  1. #define WM_COMMAND              0x0111
  2. #define WM_TIMER                0x0113  
  3. #define TIMER_ID                100
  4. #define SHVIEW_THUMBNAIL        0x702D
  5. #define SHVIEW_TILE             0x702E
  6. #define SHVIEW_ICON             0x7029
  7. #define SHVIEW_LIST             0x702B
  8. #define SHVIEW_REPORT           0x702C
  9. PUBLIC oForm
  10. oForm = NEWOBJECT( 'MyForm' ) 
  11. oForm.Show()
  12. READ EVENTS
  13. DEFINE CLASS MyForm AS form
  14.   Height = 78
  15.   Width = 293
  16.   DoCreate = .T.
  17.   AutoCenter = .T.
  18.   Caption = "Form1"
  19.   AllowOutput = .F.
  20.   Name = "Form1"
  21.   
  22.   InitViewStyle = SHVIEW_THUMBNAIL      && 你只要修改这里就可以指定缺省的打开时样式
  23.   
  24.   ADD OBJECT command1 AS commandbutton WITH ;
  25.     Top = 24, ;
  26.     Left = 180, ;
  27.     Height = 27, ;
  28.     Width = 84, ;
  29.     Caption = "打开图片", ;
  30.     Name = "command1"
  31.   PROCEDURE ToggleViewStyle
  32.     LPARAMETERS p1, p2, p3, p4
  33.     LOCAL hWndLvw
  34.     m.hWndLvw = This.FindListViewWindow()
  35.     IF ( 0 != m.hWndLvw )
  36.       KillTimer( This.hWnd, TIMER_ID )
  37.       SendMessage( m.hWndLvw, WM_COMMAND, This.InitViewStyle, 0 )
  38.     ENDIF
  39.   ENDPROC
  40.   PROCEDURE FindListViewWindow
  41.     LOCAL hWndDlg, hWndLvw
  42.     m.hWndLvw = 0
  43.     m.hWndDlg = FindWindow( '#32770', This.dlg.DialogTitle ) 
  44.     IF ( 0 != m.hWndDlg )
  45.       m.hWndLvw = FindWindowEx( m.hWndDlg, 0, 'SHELLDLL_DefView', NULL ) 
  46.     ENDIF
  47.     RETURN m.hWndLvw
  48.   ENDPROC
  49.   PROCEDURE api_decl
  50.     DECLARE Long SetTimer IN WIN32API ;
  51.       Long hWnd, Long nIDEvent, Long uElapse, Long lpTimerFunc
  52.     DECLARE Long KillTimer IN WIN32API ;
  53.       Long hWnd, Long uIDEvent
  54.     DECLARE Long FindWindow IN WIN32API ;
  55.       String lpClassName, String lpWindowName
  56.     DECLARE Long FindWindowEx IN WIN32API ;
  57.       Long hwndParent, Long hwndChildAfter, String lpszClass, String lpszWindow
  58.     DECLARE Long SendMessage IN WIN32API ;
  59.       Long hWnd, Long nMsg, Long wParams, Long lParams
  60.   ENDPROC
  61.   PROCEDURE GetPictureFile
  62.     This.api_decl()
  63.     BINDEVENT( This.hWnd, WM_TIMER, This, 'ToggleViewStyle' ) 
  64.     SetTimer( This.hWnd, TIMER_ID, 50, 0 )
  65.     This.dlg.FileName = '' 
  66.     This.dlg.ShowOpen()
  67.     UNBINDEVENT( This.hWnd, WM_TIMER )
  68.     RETURN This.dlg.FileName
  69.   ENDPROC
  70.   PROCEDURE Init
  71.     This.NewObject( 'dlg', 'olecontrol',,, 'MSComDlg.CommonDialog' ) 
  72.     This.dlg.DialogTitle = '请选择要打开的图片文件' 
  73.   ENDPROC
  74.   PROCEDURE Unload
  75.     CLEAR EVENTS
  76.   ENDPROC
  77.   PROCEDURE command1.Click
  78.     MESSAGEBOX( Thisform.GetPictureFile() )
  79.   ENDPROC
  80. ENDDEFINE
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值