终于找到了下面那几个常数的原始出处了:
http://vbnet.mvps.org/index.html?code/hooks/fileopensavedlghooklvview.htm
原来是一个叫 Brad Martinez 的高人发现的!
他还告诉我们,这些常数以及 WM_COMMAND 的消息他都是使用 spy++ 发现的!所以,能够做到聪明的使用工具也是高手和普通人的区别之一,惭愧!下面是他代码中一部分:
- // These command IDs were obtained by spelunking the File Open dialog with Spy++.
- enum {
- ODM_UNDEFINED = 0,
- ODM_VIEW_ICONS = 0x7029,
- ODM_VIEW_LIST = 0x702b,
- ODM_VIEW_DETAIL = 0x702c,
- ODM_VIEW_THUMBS = 0x702d,
- ODM_VIEW_TILES = 0x702e,
- };
- //
- // This class is used to subclass the "SHELLDLL_DefView" window in the file
- // open dialog.
- //
- class CListViewShellWnd : public CWnd
- {
- public:
- // These are the WM_COMMAND IDs to send to the shell window to set the
- // different folder views. These were obtained using Spy++ to examine
- // 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 方法就可以指定打开对话框时的任意样式了。
- #define WM_COMMAND 0x0111
- #define WM_TIMER 0x0113
- #define TIMER_ID 100
- #define SHVIEW_THUMBNAIL 0x702D
- #define SHVIEW_TILE 0x702E
- #define SHVIEW_ICON 0x7029
- #define SHVIEW_LIST 0x702B
- #define SHVIEW_REPORT 0x702C
- PUBLIC oForm
- oForm = NEWOBJECT( 'MyForm' )
- oForm.Show()
- READ EVENTS
- DEFINE CLASS MyForm AS form
- Height = 78
- Width = 293
- DoCreate = .T.
- AutoCenter = .T.
- Caption = "Form1"
- AllowOutput = .F.
- Name = "Form1"
- InitViewStyle = SHVIEW_THUMBNAIL && 你只要修改这里就可以指定缺省的打开时样式
- ADD OBJECT command1 AS commandbutton WITH ;
- Top = 24, ;
- Left = 180, ;
- Height = 27, ;
- Width = 84, ;
- Caption = "打开图片", ;
- Name = "command1"
- PROCEDURE ToggleViewStyle
- LPARAMETERS p1, p2, p3, p4
- LOCAL hWndLvw
- m.hWndLvw = This.FindListViewWindow()
- IF ( 0 != m.hWndLvw )
- KillTimer( This.hWnd, TIMER_ID )
- SendMessage( m.hWndLvw, WM_COMMAND, This.InitViewStyle, 0 )
- ENDIF
- ENDPROC
- PROCEDURE FindListViewWindow
- LOCAL hWndDlg, hWndLvw
- m.hWndLvw = 0
- m.hWndDlg = FindWindow( '#32770', This.dlg.DialogTitle )
- IF ( 0 != m.hWndDlg )
- m.hWndLvw = FindWindowEx( m.hWndDlg, 0, 'SHELLDLL_DefView', NULL )
- ENDIF
- RETURN m.hWndLvw
- ENDPROC
- PROCEDURE api_decl
- DECLARE Long SetTimer IN WIN32API ;
- Long hWnd, Long nIDEvent, Long uElapse, Long lpTimerFunc
- DECLARE Long KillTimer IN WIN32API ;
- Long hWnd, Long uIDEvent
- DECLARE Long FindWindow IN WIN32API ;
- String lpClassName, String lpWindowName
- DECLARE Long FindWindowEx IN WIN32API ;
- Long hwndParent, Long hwndChildAfter, String lpszClass, String lpszWindow
- DECLARE Long SendMessage IN WIN32API ;
- Long hWnd, Long nMsg, Long wParams, Long lParams
- ENDPROC
- PROCEDURE GetPictureFile
- This.api_decl()
- BINDEVENT( This.hWnd, WM_TIMER, This, 'ToggleViewStyle' )
- SetTimer( This.hWnd, TIMER_ID, 50, 0 )
- This.dlg.FileName = ''
- This.dlg.ShowOpen()
- UNBINDEVENT( This.hWnd, WM_TIMER )
- RETURN This.dlg.FileName
- ENDPROC
- PROCEDURE Init
- This.NewObject( 'dlg', 'olecontrol',,, 'MSComDlg.CommonDialog' )
- This.dlg.DialogTitle = '请选择要打开的图片文件'
- ENDPROC
- PROCEDURE Unload
- CLEAR EVENTS
- ENDPROC
- PROCEDURE command1.Click
- MESSAGEBOX( Thisform.GetPictureFile() )
- ENDPROC
- ENDDEFINE