The MASM Forum

General => The Campus => Topic started by: Avizma on October 14, 2013, 11:34:49 PM

Title: GetOpenFileName and select more than one file
Post by: Avizma on October 14, 2013, 11:34:49 PM
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
Title: Re: GetOpenFileName and select more than one file
Post by: jj2007 on October 15, 2013, 12:24:46 AM
MOV OPFILESTR.Flags,OFN_PATHMUSTEXIST or OFN_ALLOWMULTISELECT

And welcome to the Forum :icon14:
Title: Re: GetOpenFileName and select more than one file
Post by: dedndave on October 15, 2013, 12:53:28 AM
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)
Title: Re: GetOpenFileName and select more than one file
Post by: Avizma on October 15, 2013, 03:48:55 PM
Oh, it is realy very easy! :biggrin:
Thanks, again.
Title: Re: GetOpenFileName and select more than one file
Post by: Gunther on October 15, 2013, 07:35:26 PM
And welcome to the Forum, Avizma.

Gunther
Title: Re: GetOpenFileName and select more than one file
Post by: Vortex on October 15, 2013, 08:44:03 PM
Hi Avizma,

Welcome to the forum.

ret 4

Masm can handle it automatically. Any specific reason to type 4 ?
Title: Re: GetOpenFileName and select more than one file
Post by: jj2007 on October 15, 2013, 10:25:12 PM
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
Title: Re: GetOpenFileName and select more than one file
Post by: 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".

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?
Title: Re: GetOpenFileName and select more than one file
Post by: sys64738 on October 16, 2013, 10:16:20 PM
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.
Title: Re: GetOpenFileName and select more than one file
Post by: Avizma on October 16, 2013, 10:23:56 PM
Thanks, I am try it.
But to use SHBrowseForFolder "You must initialize Component Object Model (COM) before you call SHBrowseForFolder. " MSDN say...
Title: Re: GetOpenFileName and select more than one file
Post by: dedndave on October 17, 2013, 04:15:49 AM
simple enough...

at the beginning of the program
        INVOKE  CoInitialize,NULL
and at the end
        INVOKE  CoUninitialize
Title: Re: GetOpenFileName and select more than one file
Post by: jj2007 on October 17, 2013, 06:09:59 AM
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
Title: Re: GetOpenFileName and select more than one file
Post by: Vortex on October 17, 2013, 07:09:06 PM
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.
Title: Re: GetOpenFileName and select more than one file
Post by: Avizma on October 17, 2013, 08:59:16 PM
Vortex, you are absolutly right!
But, it is my choise and no more. ;)
Title: Re: GetOpenFileName and select more than one file
Post by: TWell on October 18, 2013, 03:15:30 AM
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);
}
Title: Re: GetOpenFileName and select more than one file
Post by: jj2007 on October 18, 2013, 04:18:52 AM
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...
Title: Re: GetOpenFileName and select more than one file
Post by: Avizma on November 27, 2013, 07:41:31 PM
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
Title: Re: GetOpenFileName and select more than one file
Post by: dedndave on November 28, 2013, 06:27:59 AM
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
Title: Re: GetOpenFileName and select more than one file
Post by: Avizma on November 28, 2013, 05:32:25 PM
Thanks, Dave!
You are absolutely right, about
MOV OPFILESTR.lpstrFileTitle,0.