Hi, dear professionals!
I use a function GetOpenFileName to open the dialog form. And I can select only one file.
Tell me, please, what I can select multi files?
Thanks.
OpenFileDialogg proc hwnd:DWORD
PUSH SIZEOF OPFILESTR
PUSH OFFSET OPFILESTR
CALL RtlZeroMemory@8
MOV OPFILESTR.lStructSize,SIZEOF OPFILESTR
MOV eax,hwnd
MOV OPFILESTR.hwndOwner,eax
MOV eax,OFFSET szFile
MOV OPFILESTR.lpstrFile,eax
MOV OPFILESTR.nMaxFile,SIZEOF szFile
MOV eax,OFFSET strFilter
MOV OPFILESTR.lpstrFilter,eax
MOV OPFILESTR.nFilterIndex,1
MOV OPFILESTR.lpstrFileTitle,0
MOV OPFILESTR.nMaxFileTitle,0
MOV OPFILESTR.lpstrInitialDir,0
MOV OPFILESTR.Flags,OFN_PATHMUSTEXIST
PUSH OFFSET OPFILESTR
CALL GetOpenFileNameA@4
ret 4
OpenFileDialogg endp
MOV OPFILESTR.Flags,OFN_PATHMUSTEXIST or OFN_ALLOWMULTISELECT
And welcome to the Forum :icon14:
welcome to the forum :t
GetOpenFileName and GetSaveFileName functions are full of caveats
the multi-file thing is an easy one
but, to get the dialog to act the way you want, you usually have to play with all the structure members - lol
http://msdn.microsoft.com/en-us/library/windows/desktop/ms646839%28v=vs.85%29.aspx (http://msdn.microsoft.com/en-us/library/windows/desktop/ms646839%28v=vs.85%29.aspx)
Oh, it is realy very easy! :biggrin:
Thanks, again.
And welcome to the Forum, Avizma.
Gunther
Hi Avizma,
Welcome to the forum.
ret 4
Masm can handle it automatically. Any specific reason to type 4 ?
Quote from: Vortex on October 15, 2013, 08:44:03 PMret 4
Masm can handle it automatically. Any specific reason to type 4 ?
You have one argument, so by sheer accident you get the right code. But beware of such exercises. For example, take this code:
MyTest proc uses esi edi ebx arg1, arg2
LOCAL ...
...
ret
ret 4
retn 4
MyTest endp... and see what you get under the hood:
00401180 ³. 5B pop ebx <<< ret starts here...
00401181 ³. 5F pop edi
00401182 ³. 5E pop esi
00401183 ³. C9 leave
00401184 À. C2 0800 retn 8 <<< ... and ends here
00401187 Ú. 5B pop ebx
00401188 ³. 5F pop edi
00401189 ³. 5E pop esi
0040118A ³. C9 leave
0040118B À. C2 0400 retn 4 <<< ... ret 4 ends here
0040118E . C2 0400 retn 4 <<< ... this is retn 4
I am use ret 4, because to me, more flexible is call a procedures, without "invoke".
But, tell me, please, what I can select all files, in the directory?
I have idea, get from a OPFILESTR.lpstrFile path, and then use it in the functions FindFirstFile, FindNextFile.
May be, is more easy way?
If you want only a directory name from the user selection, then you can use
SHBrowseForFolder (http://msdn.microsoft.com/en-us/library/windows/desktop/bb762115%28v=vs.85%29.aspx) instead of using the file open dialog. And then use FindFirst/FindNext loop to go through all the files.
Thanks, I am try it.
But to use SHBrowseForFolder "You must initialize Component Object Model (COM) before you call SHBrowseForFolder. " MSDN say...
simple enough...
at the beginning of the program
INVOKE CoInitialize,NULL
and at the end
INVOKE CoUninitialize
It works without Coxx (at least under WinXP SP3), but even with the Co-calls it's only a 40-liner:
include \masm32\include\masm32rt.inc
.code
Browse4Folder proc pCaption, pBuffer
LOCAL bInfo:BROWSEINFO, initialPath[MAX_PATH]:BYTE
mov eax, esp
.Repeat
and dword ptr [eax], 0 ; clear the locals
add eax, 4
.Until eax>=ebp
m2m bInfo.lpszTitle, pCaption
mov bInfo.lpfn, cbSHB ; callback
lea eax, initialPath
mov bInfo.lParam, eax
invoke GetCurrentDirectory, MAX_PATH, eax
m2m bInfo.pszDisplayName, pBuffer
.if rv(SHBrowseForFolder, addr bInfo)
invoke SHGetPathFromIDList, eax, pBuffer
xchg eax, pBuffer ; return a pointer to the buffer
.endif
ret
cbSHB: ; hwnd:HWND, uMsg:UINT, lParam:LPARAM, lpData:LPARAM
.if dword ptr [esp+8]==BFFM_INITIALIZED ; start with current folder
invoke SendMessage, [esp+16], BFFM_SETSELECTION, TRUE, [esp+16]
.endif
retn 4*4
Browse4Folder endp
start:
sub esp, MAX_PATH ; create a buffer
invoke CoInitialize, NULL
invoke Browse4Folder, chr$("Select a folder"), esp
.if !eax
mov eax, chr$("You cancelled")
.endif
MsgBox 0, eax, "Selected folder:", MB_OK
add esp, MAX_PATH ; release the buffer
invoke CoUninitialize
exit
end start
Quote from: Avizma on October 16, 2013, 09:33:54 PM
I am use ret 4, because to me, more flexible is call a procedures, without "invoke".
While doing some code optimizations, you can do without invoke but this macro saves time to avoid the extra typing.
Vortex, you are absolutly right!
But, it is my choise and no more. ;)
For selecting folder name with GetOpenFileName() in C
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <commdlg.h>
#pragma comment(lib, "kernel32.lib")
#pragma comment(lib, "user32.lib")
#pragma comment(lib, "comdlg32.lib")
static UINT_PTR CALLBACK OFNHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
{
if (uiMsg == WM_INITDIALOG) {
HWND hWnd = GetParent(hdlg);
if (hWnd) {
HWND hCtl;
hCtl = GetDlgItem(hWnd, 0x441);
ShowWindow(hCtl, SW_HIDE);
hCtl = GetDlgItem(hWnd, 0x470);
ShowWindow(hCtl, SW_HIDE);
hCtl = GetDlgItem(hWnd, 0x442);
ShowWindow(hCtl, SW_HIDE);
hCtl = GetDlgItem(hWnd, 0x47C);
ShowWindow(hCtl, SW_HIDE);
}
}
return 0;
}
static BOOL FileFolderBrowse(HWND hwnd, TCHAR *szFolder, TCHAR *szTitle)
{
OPENFILENAME ofn;
memset(&ofn, 0, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hwnd;
ofn.lpstrFilter = TEXT("Folder only\0$$$.$$$\0\0");
ofn.lpstrFile = szFolder;
ofn.nMaxFile = MAX_PATH;
ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY
| OFN_ENABLEHOOK | OFN_ENABLESIZING | OFN_DONTADDTORECENT;
ofn.lpstrTitle = szTitle;
ofn.lpfnHook = OFNHookProc;
#if (_WIN32_WINNT >= 0x0500)
ofn.FlagsEx = OFN_EX_NOPLACESBAR;
#endif
lstrcpy(szFolder, "Folder$$$");
if (GetOpenFileName(&ofn))
return TRUE;
else
return FALSE;
}
int __cdecl WinMainCRTStartup(void)
{
TCHAR szFolder[MAX_PATH];
if (FileFolderBrowse(0, szFolder, TEXT("Select folder"))) {
MessageBox(0, szFolder, 0, MB_OK);
}
ExitProcess(0);
}
Quote from: TWell on October 18, 2013, 03:15:30 AM
For selecting folder name with GetOpenFileName() in C
Compiles fine, but returns always FALSE in WinXP SP3...
In summary, I finded way to use the GetOpenFileName for select folder (not files).
I repeat a posts of this forum, may be. But I think, this topic, will be more complete.
OpenFileDialogg proc hwnd:DWORD
PUSH SIZEOF OPFILESTR
PUSH OFFSET OPFILESTR
CALL RtlZeroMemory@8
PUSH SIZEOF szFile
PUSH OFFSET szFile
CALL RtlZeroMemory@8
LEA EAX, [szFile]
MOV BYTE PTR [EAX], '*'
MOV OPFILESTR.lStructSize,SIZEOF OPFILESTR
MOV EAX, hwnd
MOV OPFILESTR.hwndOwner, EAX
MOV EAX, OFFSET szFile
MOV OPFILESTR.lpstrFile, EAX
MOV OPFILESTR.nMaxFile, SIZEOF szFile
MOV EAX, OFFSET strFilter
MOV OPFILESTR.lpstrFilter, EAX
MOV OPFILESTR.nFilterIndex,1
MOV OPFILESTR.lpstrFileTitle,0
MOV OPFILESTR.nMaxFileTitle,0
MOV OPFILESTR.lpstrInitialDir,0
MOV OPFILESTR.Flags, OFN_NOVALIDATE
PUSH OFFSET OPFILESTR
CALL GetOpenFileNameA@4
ret 4
OpenFileDialogg endp
no need to zero the entire szFile buffer
mov word ptr szFile,'*'
sets it to '*',0
also, if you have cleared out the OPENFILENAME structure, no need for...
MOV OPFILESTR.lpstrFileTitle,0
MOV OPFILESTR.nMaxFileTitle,0
MOV OPFILESTR.lpstrInitialDir,0
anyways - it looks interesting - i'll have to try it out :t
Thanks, Dave!
You are absolutely right, about
MOV OPFILESTR.lpstrFileTitle,0.