News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

GetOpenFileName and select more than one file

Started by Avizma, October 14, 2013, 11:34:49 PM

Previous topic - Next topic

Avizma

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

jj2007

MOV OPFILESTR.Flags,OFN_PATHMUSTEXIST or OFN_ALLOWMULTISELECT

And welcome to the Forum :icon14:

dedndave

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

Avizma


Gunther

You have to know the facts before you can distort them.

Vortex

Hi Avizma,

Welcome to the forum.

ret 4

Masm can handle it automatically. Any specific reason to type 4 ?

jj2007

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

Avizma

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?

sys64738

If you want only a directory name from the user selection, then you can use
SHBrowseForFolder instead of using the file open dialog. And then use FindFirst/FindNext loop to go through all the files.

Avizma

Thanks, I am try it.
But to use SHBrowseForFolder "You must initialize Component Object Model (COM) before you call SHBrowseForFolder. " MSDN say...

dedndave

simple enough...

at the beginning of the program
        INVOKE  CoInitialize,NULL
and at the end
        INVOKE  CoUninitialize

jj2007

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

Vortex

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.

Avizma

Vortex, you are absolutly right!
But, it is my choise and no more. ;)

TWell

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);
}