flat assembler
Message board for the users of flat assembler.

Index > Windows > Common dialogs (newbie)

Author
Thread Post new topic Reply to topic
gnomen



Joined: 07 Oct 2003
Posts: 13
gnomen 07 Oct 2003, 21:11
Can someone tell me what is wrong with this code:
Code:
lpfn rb 1000h
txt_filter db 'Text files',0,'*.TXT',0
ofn OPENFILENAME
...
mov [ofn.lpstrFile],lpfn
mov [lpfn],0
mov [ofn.lpstrFilter],txt_filter
mov [ofn.Flags],OFN_EXPLORER+OFN_FILEMUSTEXIST+OFN_HIDEREADONLY
mov [ofn.lpstrTitle],NULL
invoke  GetOpenFileName,ofn
    
Post 07 Oct 2003, 21:11
View user's profile Send private message Reply with quote
gnomen



Joined: 07 Oct 2003
Posts: 13
gnomen 07 Oct 2003, 23:08
Code:
;the following code is meant to show an open file dialog
format PE GUI 4.0
entry start

include '%include%/win32a.inc'

section '.data' data readable writeable

  hinstance dd ?

  ofn OPENFILENAME
  fname rb 100h

section '.code' code readable executable

  start:
        ;get the instance handle
        invoke  GetModuleHandle,0
        mov     [hinstance],eax

        ;init the OPENFILENAME structure
        mov     [ofn.lStructSize], sizeof.OPENFILENAME
        mov     eax,[hinstance]
        mov     [ofn.hInstance],eax
        mov     [ofn.hwndOwner],HWND_DESKTOP

        ;show the open dialog
        invoke  GetOpenFileName, ofn

        ;exit the program
        invoke  ExitProcess, hinstance

section '.idata' import data readable writeable

  library kernel,'KERNEL32.DLL',\
          comdlg,'COMDLG32.DLL'

  import kernel,\
         GetModuleHandle,'GetModuleHandleA',\
         ExitProcess,'ExitProcess'

  import comdlg,\
         GetOpenFileName,'GetOpenFileNameA'    
Post 07 Oct 2003, 23:08
View user's profile Send private message Reply with quote
gnomen



Joined: 07 Oct 2003
Posts: 13
gnomen 08 Oct 2003, 00:32
I added a variable for the lpstrFile element, but now the dialog won't even show Mad
Code:
section '.data' data readable writeable
;...
fname dd ?
msg_title  db 'Path',0
;...
section '.code' code readable executable
  start:
        ;get the instance handle
        invoke  GetModuleHandle,0
        mov     [hinstance],eax

        ;init the OPENFILENAME structure
        mov     [ofn.lStructSize], sizeof.OPENFILENAME
        mov     eax,[hinstance]
        mov     [ofn.hInstance],eax
        mov     [ofn.hwndOwner],HWND_DESKTOP

        ;added to be able to get the file's path later
        mov     [ofn.lpstrFile],fname

        ;show the open dialog
        invoke  GetOpenFileName,ofn ;<-- it won't show! because of the fname var, i think

        ;test if I can get the file name
        invoke  MsgBox,HWND_DESKTOP,fname,msg_title,MB_OK

        ;exit the program
        invoke  ExitProcess, hinstance 
    


The MessageBox shows 'Path' in the title, but no text is displayed...
Any ideas on how to make it work?
Post 08 Oct 2003, 00:32
View user's profile Send private message Reply with quote
pelaillo
Missing in inaction


Joined: 19 Jun 2003
Posts: 878
Location: Colombia
pelaillo 08 Oct 2003, 07:34
gnomen,
ofn.lpstrFile is a pointer to a string, but as you declared your fname variable it is actually undefined pointer:

fname dd ?

In order to get the filename, you need to provide a buffer for hold the returned string, not a pointer (see your previous example):
Code:
buffer rb 100h
;....
mov    [fname],buffer
mov    [ofn.lpstrFile],[fname]
;or directly
;mov    [ofn.lpstrFile],buffer
    
Post 08 Oct 2003, 07:34
View user's profile Send private message Yahoo Messenger Reply with quote
gnomen



Joined: 07 Oct 2003
Posts: 13
gnomen 13 Oct 2003, 15:18
pelaillo,
Thanks for the tip, but still no luck...
I am posting the entire code now so maybe someone can see what's wrong with it:

Code:
format PE GUI 4.0
entry start

include '%include%\win32a.inc'

section '.data' data readable writeable
  hinstance dd ?
  buffer rb 100h
  fname dd ?
  msg_title  db 'Path',0
  ofn OPENFILENAME

section '.code' code readable executable
  start:
        ;get the instance handle
        invoke  GetModuleHandle,0
        mov     [hinstance],eax

        ;init the OPENFILENAME structure
        mov     [ofn.lStructSize], sizeof.OPENFILENAME
        mov     eax,[hinstance]
        mov     [ofn.hInstance],eax
        mov     [ofn.hwndOwner],HWND_DESKTOP

        ;added to be able to get the file's path later
        mov     [fname],buffer
        mov     [ofn.lpstrFile],fname ;<-- If I comment this out, the next line works, but then I won't get the filename ;P
; and if i do: mov [ofn.lpstrFile],[fname] I get a compiler error, Invalid operand.

        ;show the open dialog
        invoke  GetOpenFileName,ofn ;<-- still won't show if I have something in the ofn.lpstrFile

        ;test if I can get the file name
        invoke  MsgBox,HWND_DESKTOP,fname,msg_title,MB_OK

        ;exit the program
        invoke  ExitProcess, hinstance

section '.idata' import data readable writeable
  library kernel,'KERNEL32.DLL',\
          comdlg,'COMDLG32.DLL',\
          user,'USER32.DLL'

  import kernel,\
         GetModuleHandle,'GetModuleHandleA',\
         ExitProcess,'ExitProcess'

  import comdlg,\
         GetOpenFileName,'GetOpenFileNameA'

  import user,\
         MsgBox,'MessageBoxA'                
    
Post 13 Oct 2003, 15:18
View user's profile Send private message Reply with quote
inskipp



Joined: 23 Jun 2003
Posts: 25
Location: Poland
inskipp 13 Oct 2003, 18:57
hello gnomen
You don't have to use the poiter fname if you have static buffer. You can simply pass its adress to functions:
Code:
        mov     [ofn.lStructSize], sizeof.OPENFILENAME 
        mov     eax,[hinstance] 
        mov     [ofn.hInstance],eax 
        mov     [ofn.hwndOwner],HWND_DESKTOP         
        mov     [ofn.nMaxFile],100h  ;this isn't requeried, but i think it schuld be here
        mov     [ofn.lpstrFile],buffer
        invoke  GetOpenFileName,ofn
        invoke  MsgBox,HWND_DESKTOP,buffer,msg_title,MB_OK
</code]
Now it works
    
Post 13 Oct 2003, 18:57
View user's profile Send private message ICQ Number Reply with quote
gnomen



Joined: 07 Oct 2003
Posts: 13
gnomen 14 Oct 2003, 12:42
Yes! good! Very Happy

I believe the nMaxFile must have been the bad boy, as I've tried passing the buffer directly to lpstrFile before.
Post 14 Oct 2003, 12:42
View user's profile Send private message Reply with quote
gnomen



Joined: 07 Oct 2003
Posts: 13
gnomen 14 Oct 2003, 18:30
How can I trim the filename?
ie. is there a way to make a buffer of dynamic size and move it there?

sample output:
"D:\Thomas\{DEVELOP}\{PROJEKT}\fasm\Common Dialogs\GetOpenFileName.ASM<ton-of-nulls>"
It should be:
"D:\Thomas\{DEVELOP}\{PROJEKT}\fasm\Common Dialogs\GetOpenFileName.ASM"

Btw, the quotes aren't part of the output, I just put them there to try and illustrate Shocked
Post 14 Oct 2003, 18:30
View user's profile Send private message Reply with quote
roticv



Joined: 19 Jun 2003
Posts: 374
Location: Singapore
roticv 15 Oct 2003, 13:16
HeapCreate + HeapAlloc?
Post 15 Oct 2003, 13:16
View user's profile Send private message Visit poster's website MSN Messenger Reply with quote
gnomen



Joined: 07 Oct 2003
Posts: 13
gnomen 15 Oct 2003, 15:27
Quote:
HeapCreate + HeapAlloc?


It might work, but I need to find the size of the filename (it doesn't seem to be returned to the OPENFILENAME structure).
Post 15 Oct 2003, 15:27
View user's profile Send private message Reply with quote
roticv



Joined: 19 Jun 2003
Posts: 374
Location: Singapore
roticv 15 Oct 2003, 17:01
MAX_PATH is defined to be 256 if i am not wrong. for longer pathnames, unciode is needed.
Post 15 Oct 2003, 17:01
View user's profile Send private message Visit poster's website MSN Messenger Reply with quote
gnomen



Joined: 07 Oct 2003
Posts: 13
gnomen 15 Oct 2003, 23:09
Sorry I wasn't being specific - what I meant was that if the returned pathname is shorter than max_path then how is it possible to know how long it is?
For example: I allocate a buffer of max_path bytes (buffer rb 100h) and mov it to [ofn.lpstrFile]. Then I mov [ofn.nMaxFile], 100h (I could use a pointer for this, but it doesn't seem to be changed by the function). Now I invoke GetOpenFileName, ofn... Fine, the dialog pops up, and I do get the pathname.. The sad part is that the buffer is still max_path long and if I WriteFile it, it writes the pathname + the empty rest of the buffer.
I was thinking of using StrCopy or an equivalent (there's some new "secure" version of it), but I need to know the amount of bytes to copy.

Do you know if/how this can be done?

Thanks for helping Wink
Post 15 Oct 2003, 23:09
View user's profile Send private message Reply with quote
roticv



Joined: 19 Jun 2003
Posts: 374
Location: Singapore
roticv 16 Oct 2003, 13:26
Use strlen to get length of string. Then invoke WriteFile with that number instead of 256. That will definitely solve the problem.
Post 16 Oct 2003, 13:26
View user's profile Send private message Visit poster's website MSN Messenger Reply with quote
gnomen



Joined: 07 Oct 2003
Posts: 13
gnomen 18 Oct 2003, 16:24
Quote:
Use strlen to get length of string.


I've downloaded the Fresh strlib, but how do I use it?? move the string to eax then stdcall it or what?

Example code would be much appreciated!

Thanks for replies Smile
Post 18 Oct 2003, 16:24
View user's profile Send private message Reply with quote
scientica
Retired moderator


Joined: 16 Jun 2003
Posts: 689
Location: Linköping, Sweden
scientica 18 Oct 2003, 16:45
Here is an example (read the strlib.asm header comment for instructions on how to implent it in your sources, the funcitons in it has comments with their usage,args and return values. Hope fully I'll soon finish the first realease of Harsyra so that users can get some sort of "easy to read/use" documentation, but for now looking in the sources is the only way to get the docsumention for it.)

Code:
  szString1 db 'This string',0
...

  ; create a new string
  stdcall StrNew, 0
  mov     [ebx+TComment.pContent],eax ; eax is the handle to the string
  ; copy the "standard byte string" in esi to it:
  mov     esi, szString1
  stdcall StrCopy, eax, esi      ; copy/set the filename

  stdcall StrLen, [ebx+TComment.pContent] ; returns length in eax
  stdcall StrLen, szString1 ; van be used on normal strings too.

  stdcall StrPtr, [ebx+TComment.pContent] ; get the pointer to the string, so we can for instance print it to stdout:
  stdcall PrintStringLn, eax ; (non StrLib function)
    

_________________
... a professor saying: "use this proprietary software to learn computer science" is the same as English professor handing you a copy of Shakespeare and saying: "use this book to learn Shakespeare without opening the book itself.
- Bradley Kuhn
Post 18 Oct 2003, 16:45
View user's profile Send private message Visit poster's website Reply with quote
decard



Joined: 11 Sep 2003
Posts: 1092
Location: Poland
decard 18 Oct 2003, 16:46
Code:
stdcall StrLen, my_string    

where my_string is a pointer (or handle) to your string.
Post 18 Oct 2003, 16:46
View user's profile Send private message Visit poster's website Reply with quote
gnomen



Joined: 07 Oct 2003
Posts: 13
gnomen 18 Oct 2003, 17:29
I can't understand this:
Code:
;--< How to use it >-----------------------------------------------------------------
; 1. Include "strutils.inc" somewhere in the begining of main file.
    

That file doesn't exists! I tried including "strlib.inc" instead, but no success, since fasmw can't find the function "InitStrings" or any other, like "StrNew"
Code:
; 2. Define structure "StrTable" of type "TStrTable" somewhere in data section.
    

Ok, that I can do.
Code:
; 3. Before using of library functions, call "InitStrings"
    

I've tried using stdcall InitStrings (as #5 tells me, I've read the header to InitStrings. But it doesn't say how it should be called), but get an invalid operand -
It seems to me, by looking at the code in strlib.asm, that esi and ebx should contain some arguments... What might they be?
This is how far I've made it.
Code:
; 4. After last use of the library (probably on close of application),
;    call "FreeStrings" to free all used memory.
; 5. Some functions are with register parameter passing, other with "stdcall"
;    parameter passing. Read the header descriptions of the functions.
;------------------------------------------------------------------------------------     


Sorry for being a complete n00b at assembly Wink
Post 18 Oct 2003, 17:29
View user's profile Send private message Reply with quote
decard



Joined: 11 Sep 2003
Posts: 1092
Location: Poland
decard 18 Oct 2003, 17:53
Actually this is our mistake Embarassed
StrLib is made mostly for Fresh, and it uses Fresh's libraries. Also, the "How to use" comment is a bit outdated. Try this:

;--< How to use it >--------------------------------------------------------------
; 0. StrLib requires Fresh stdcallex.inc library. You have to include it in the
; begining of your main sourcefile.
; 1. Include "strlib.inc" somewhere in the begining of main file.
; 2. If you are don't want to use Fresh macroses for global data (globals.inc),
; then you have to define structure "StrTable" of type "TStrTable" somewhere in
; data section, and comment lines 59-61 of this file.
; 3. Before using of library functions, call "InitStrings"
; 4. After last use of the library (probably on close of application),
; call "FreeStrings" to free all used memory.
;--------------------------------------------------------------------------------

...and this version of StrLib (I added StdCallEx.inc to the package)

Hope it will help you,
Decard
Post 18 Oct 2003, 17:53
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.