News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Newb here.

Started by BRONiUS, December 28, 2006, 01:25:44 PM

Previous topic - Next topic

BRONiUS

HI! I am new to this forum and mostly newb on MASM. I have few programs programmed by it. So, now I wanted to program a file viewer myself. I 'ripped' some code from one tut, added mine, but it wasn't good. Maybe someone could help me fixing the errors? The code is below. Please help me :)


.386
.model flat,stdcall
option casemap:none
include C:\masm32\include\windows.inc
include C:\masm32\include\kernel32.inc
include C:\masm32\include\user32.inc
include C:\masm32\include\comctl32.inc
includelib C:\masm32\lib\comctl32.lib
includelib C:\masm32\lib\kernel32.lib
includelib C:\masm32\lib\user32.lib
includelib C:\masm32\lib\shell32.lib
include C:\masm32\include\shell32.inc


MainWindow proto :DWORD
ViewFile proto :DWORD, :DWORD
RunFile proto :BYTE

.data
classname db "ListViewWinClass",0
windowname db "FileBrowser",0
ListViewName db "SysListView32",0
Filename db "*.*",0
Header db "File name",0
DefaultPath db "C:\",0
EditName db "edit",0
ButClass db "button",0
ButName db "Gooo!",0

.data?
hInstance HINSTANCE ?
hList dd ?
hEdit dd ?
hButton dd ?
buffer db 256 dup (?)

.code
start:

invoke GetModuleHandle, NULL
mov hInstance, eax
invoke MainWindow, hInstance
invoke ExitProcess, 0
invoke InitCommonControls

MainWindow proc

LOCAL message:MSG
LOCAL hWindow:HWND
LOCAL WC:WNDCLASSEX
mov WC.cbSize,SIZEOF WNDCLASSEX
mov WC.style, NULL
mov WC.IpfnWndProc, OFFSET WindowProc
mov WC.cbClsExtra, NULL
mov WC.cbWndExtra, NULL
push hInstance
pop WC.hInstance
invoke LoadIcon, NULL, IDI_APPLICATION
mov WC.hIcon, eax
mov WC.hIconSm, eax
invoke LoadCursor, NULL, IDC_ARROW
mov WC.hCursor, eax
mov WC.hbrBackground, COLOR_WINDOW+1
mov WC.IpszMenuName, NULL
mov WC.IpszClassName, OFFSET classname
invoke RegisterClassEx, addr WC
invoke CreateWindowEx, NULL, addr classname, addr windowname,\
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,\
CW_USEDEFAULT,  CW_USEDEFAULT, NULL,
NULL, hInstance, NULL
mov hWindow, eax
invoke ShowWindow, hWindow, SW_SHOWDEFAULT

.While TRUE
invoke GetMessage, addr message, NULL, 0, 0
.BREAK .IF (!eax)
invoke TranslateMessage, addr message
invoke DispatchMessage, addr message
.endw
MainWindow endp

WindowProc proc hWnd:HWND, WinMsg:UINT, wParam:WPARAM, lParam:LPARAM
.if WinMsg==WM_DESTROY
invoke PostQuitMessage, NULL
ret

.elseif WinMsg==WM_CREATE
invoke CreateWindowEx,0,addr EditName,0,\
WS_DLGFRAME+WS_CHILD+ES_AUTOHSCROLL,
0,0,710,25,\
hWnd,0,hInstance,0
mov hEdit, eax
invoke ShowWindow,hEdit,SW_SHOWDEFAULT
invoke SendMessage,hEdit,WM_SETTEXT,0,Addr writepath
invoke SendMessage,hEdit,EM_SETSEL,0,-1
invoke CreateWindowEx,0 , addr ButClass, addr ButName,
WS_CHILD+BS_DEFPUSHBUTTON+BS_TEXT+BS_VCENTER,
710,0,50,25,hInstance,0
mov hButton, eax
invoke ShowWindow,hButton,SW_SHOW
invoke CreateWindowEx, NULL, addr ListViewName, NULL,\
WS_CHILD+LVS_REPORT+LVS_ALIGNLEFT+LVS_SORTASCENDING,\
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,\
CW_USEDEFAULT, hWnd, NULL, hInstance, NULL
mov hList, eax
invoke ShowWindow, hList, SW_SHOW
call InsertColumn
invoke SetCurrentDirectory, addr DefaultPath
call ShowAll

.ElseIf WinMsg==WM_COMMAND
mov eax,wparam
shr eax,16
.IF eax==BN_CLICKED
mov eax,lParam
.If eax==hButton
invoke RunFile,1
.endif
.endif
.ElseIf WinMsg==WM_SIZE
mov eax,lParam
mov edx,eax
and eax,0FFFFH
shr edx,16
push eax
invoke MoveWindow,hList, 0, 0, eax,edx,TRUE
pop eax
sub eax,50
push eax
Invoke MoveWindow,hEdit,0,0,eax,25,TRUE
pop eax
invoke MoveWindow,hButton,eax,0,50,25,TRUE

.ElseIF WinMsg==WM_NOTIFY
mov edi,lParam
assume edi:ptr NMHDR
mov eax,[edi].hwndFrom
.if eax==hList
.if [edi].code==NM_DBLCLK
Invoke RunFile,0
.ElseIf [edi].code==NM_RETURN
Invoke RunFile,0
.endif
.endif
assume edi:nothing

.else
invoke DefWindowProc, hWnd, WinMsg, wParam, lParam
ret
.endif
xor eax,eax
ret

InsertColumn proc

LOCAL lvc:LV_COLUMN
mov lvc.imask,LVCF_FMT+LVCF_WIDTH+LVCF_TEXT
mov lvc.fmt,LVCFMT_LEFT
mov lvc.lx,100
mov lvc.pszText, OFFSET Header
invoke SendMessage, hList, LVM_INSERTCOLUMN, 0, addr lvc

ret

InsertColumn endp
ShowAll proc, WinFind:DWORD
uses edi

LOCAL WinFind:WIN32_FIND_DATA
LOCAL FHandle:DWORD
invoke FindFirstFile, addr FileName, addr WinFind
.if eax!=INVALID_HANDLE_VALUE
mov FHandle, eax
xor edi, edi
.while eax!=0
invoke ViewFile, edi, addr WinFind
inc edi
invoke FindNextFile, FHandle, addr WinFind
.endw
invoke FindClose, FHandle
.endif

ret

ShowAll endp

ViewFile proc, eilute:DWORD, WinFind:DWORD
uses edi
LOCAL LVI:LV_ITEM
mov edi, WinFind
assume edi:ptr WIN32_FIND_DATA
mov LVI.imask,LVIF_TEXT
push eilute
pop LVI.iItem
mov LVI.iSubItem, 0
lea eax,[edi].cFileName
mov LVI.pszText,eax
push eilute
pop LVI.lParam
invoke SendMessage, hList, LVM_INSERTITEM, 0, addr lvi
assume edi:nothing

ret

ViewFile endp

RunFile proc EorL:BYTE

LOCAL lvi:LV_ITEM

.If EorL==1
invoke SendMessage,hEdit,WM_GETTEXT,256,addr buffer
.Else
invoke SendMessage,hList,LVM_GETNEXTITEM, -1, LVNI_FOCUSED
mov lvi.iItem,eax
mov lvi.imask,LVIF_TEXT
lea eax,buffer
mov lvi.pszText,eax
mov lvi.iSubItem,0
mov lvi.cchTextMax,256
invoke SendMessage, hList, LVM_GETITEM, 0, addr lvi
.EndIf
  invoke GetFileAttributes, addr buffer
and eax,10h ;FILE_ATTRIBUTE_DIRECTORY=10h, LOL...
.If eax!=0
invoke SendMessage, hList, LVM_DELETEALLITEMS, 0, 0
invoke SetCurrentDirectory, addr buffer
call FillList
.else
invoke ShellExecuteA,0,0,addr buffer,0,0,SW_SHOWDEFAULT
.endif

ret
RunFile endp

end start



TNick

Welcome!
Quick notes:
1) When you post long code, I would say it's better to attach it to the message
2) You are calling MainWindow with a argument, but the proc is defined without any arguments, so, probably, the stack is debalanced.
[edit]
or, better yet, forget about that argument. You are saving the module handle in a global variable, then you are passing it using the stack to a function. There's no need for that. Just change
MainWindow   proto  :DWORD
in
MainWindow   proto

and

invoke   MainWindow, hInstance
in
invoke   MainWindow
[/edit]
I will take a closer look in a while. :)

Regards,
Nick

PBrennick

I think you should change


invoke   GetModuleHandle, NULL
mov hInstance, eax
invoke MainWindow
invoke ExitProcess, 0
invoke InitCommonControls


to


invoke  GetModuleHandle, NULL
mov     hInstance, eax
invoke  InitCommonControls
invoke  MainWindow
invoke  ExitProcess, 0


Paul
The GeneSys Project is available from:
The Repository or My crappy website

BRONiUS

@Nick, next time I will and thanks for your help.
@Paul, I changed that. Thanks.

Wow guys, thanks. I still get errors, but less then previous time :) Here are my errors:

D:\RadASM\File Viewer.asm(94) : error A2006: undefined symbol : writepath
D:\RadASM\File Viewer.asm(94) : error A2114: INVOKE argument type mismatch : argument : 4
D:\RadASM\File Viewer.asm(96) : error A2137: too few arguments to INVOKE
D:\RadASM\File Viewer.asm(154) : error A2144: cannot nest procedures
D:\RadASM\File Viewer.asm(156) : error A2012: PROC, MACRO, or macro repeat directive must precede LOCAL
D:\RadASM\File Viewer.asm(161) : error A2006: undefined symbol : lvc
D:\RadASM\File Viewer.asm(161) : error A2114: INVOKE argument type mismatch : argument : 4
D:\RadASM\File Viewer.asm(166) : error A2144: cannot nest procedures
D:\RadASM\File Viewer.asm(167) : error A2008: syntax error : edi
D:\RadASM\File Viewer.asm(169) : error A2012: PROC, MACRO, or macro repeat directive must precede LOCAL
D:\RadASM\File Viewer.asm(170) : error A2012: PROC, MACRO, or macro repeat directive must precede LOCAL
D:\RadASM\File Viewer.asm(171) : error A2006: undefined symbol : FileName
D:\RadASM\File Viewer.asm(171) : error A2114: INVOKE argument type mismatch : argument : 1
D:\RadASM\File Viewer.asm(178) : error A2006: undefined symbol : FHandle
D:\RadASM\File Viewer.asm(178) : error A2114: INVOKE argument type mismatch : argument : 1
D:\RadASM\File Viewer.asm(180) : error A2006: undefined symbol : FHandle
D:\RadASM\File Viewer.asm(180) : error A2114: INVOKE argument type mismatch : argument : 1
D:\RadASM\File Viewer.asm(187) : error A2144: cannot nest procedures
D:\RadASM\File Viewer.asm(188) : error A2008: syntax error : edi
D:\RadASM\File Viewer.asm(189) : error A2012: PROC, MACRO, or macro repeat directive must precede LOCAL
D:\RadASM\File Viewer.asm(200) : error A2006: undefined symbol : lvi
D:\RadASM\File Viewer.asm(200) : error A2114: INVOKE argument type mismatch : argument : 4
D:\RadASM\File Viewer.asm(207) : error A2144: cannot nest procedures
D:\RadASM\File Viewer.asm(209) : error A2012: PROC, MACRO, or macro repeat directive must precede LOCAL
D:\RadASM\File Viewer.asm(221) : error A2006: undefined symbol : lvi
D:\RadASM\File Viewer.asm(221) : error A2114: INVOKE argument type mismatch : argument : 4
D:\RadASM\File Viewer.asm(236) : fatal error A1010: unmatched block nesting : WindowProc

I attached that file. And edited first post, there was error in there. I am looking forward to your replies, guys. :)


Luke



[attachment deleted by admin]

TNick

He, he! Some months ago my error list was longer than the file itself, too!   :green2

Some tips:
- the error message gives you important information:
File Viewer.asm(94) - file and line number wher the error was found
for first error:
QuoteD:\RadASM\File Viewer.asm(94) : error A2006: undefined symbol : writepath
line 94 say:
invoke SendMessage,hEdit,WM_SETTEXT,0,Addr writepath
but there is no writepath in the entire file... so, the symbol writepath is undefined
- to split a line, use the backslash:
invoke CreateWindowEx,0 , addr ButClass, addr ButName, \
WS_CHILD+BS_DEFPUSHBUTTON+BS_TEXT+BS_VCENTER,\
710,0,50,25,hInstance,0

- any
WindowProc proc
should have a coresponding
WindowProc endp
because, if it hasn't, you will have a bounch of errors for next lines :)

Fix this and the list will be a lot smaller.

[edit]
just noticed that you used this:
WS_CHILD+BS_DEFPUSHBUTTON+BS_TEXT+BS_VCENTER
to tell the style of a window. the flags should be OR'ed, not added
WS_CHILD or BS_DEFPUSHBUTTON or BS_TEXT or BS_VCENTER
[/edit]

Nick

ramguru

Code ripping is a very bad habit ! However, I made your prog working.

[attachment deleted by admin]

BRONiUS

OMG guys, I love both of you  :bg Thanks Nick for pointing my mistakes  :P And ramguru, you too. Really thank you. And I ripped some of that code from journal, so I had to type everything AND it was meant to be compiled, it was a tutorial.

Luke

TNick


Ehtyar

Quote from: PBrennick on December 28, 2006, 02:59:53 PM
I think you should change


invoke   GetModuleHandle, NULL
mov hInstance, eax
invoke MainWindow
invoke ExitProcess, 0
invoke InitCommonControls


to


invoke  GetModuleHandle, NULL
mov     hInstance, eax
invoke  InitCommonControls
invoke  MainWindow
invoke  ExitProcess, 0


Paul

Now, THERE is a question I've been meaning to ask for....well a bloody long time. Why is it that InitCommonControls/InitCommonControlsEx goes at the END of the startup code? Been driving me crazy for ages....

Ehtyar.

PBrennick

Actually it doesn't need to be moved as I said. I am just a purist. It is included in the code to force the DLL to load but at run time it does not need to be executed hence he put it after ExitProcess.
Paul
The GeneSys Project is available from:
The Repository or My crappy website

Ehtyar

So why for InitCommonControlsEx do we set the class of controls to be loaded if the API itself is never executed?

Ehtyar.

zooba

Quote from: Ehtyar on January 01, 2007, 10:57:59 PM
So why for InitCommonControlsEx do we set the class of controls to be loaded if the API itself is never executed?

Presumably for improved load time (ie. only load the classes you need). Though it will give an error if one of the specified classes could not be loaded (if it's an older version of comctl32) so you can't arbitrarily load all the classes all at once (this is based on one experience with it, correct me if I'm wrong).

AFAIK, InitCommonControlsEx does need to execute before you create any windows of a common control class, but I haven't tried it. InitCommonControls is obsolete and was used only to ensure that the linker didn't discard the reference.

Cheers,

Zooba :U

MichaelW

At least under Windows 2000 there is no need to actually call InitCommonControlsEx. In my crude tests the difference in load time was much smaller than the run to run variation. The average over several hundred runs showed the version that called InitCommonControlsEx to be slightly slower than the version that did not, but even so, IMO it is silly to not call InitCommonControlsEx, considering that the call must be coded, and that the call may be necessary on some systems.
eschew obfuscation

zooba

Still based on my one experience with this, I found the call to InitCommonControlsEx was required under Windows XP with no manifest (MSDN says it's not needed when you have a manifest but I didn't check) and the call had to succeed. Some control classes failed to load in which case none of them were usable.

In any case, Microsoft have documented that the call is required. Maybe it is, maybe it isn't, as developers we aren't to question that. If one day (Vista?) they make it necessary to call InitCommonControlsEx and your program breaks because you don't, they've covered themselves by documenting it.

Bottom line, call InitCommonControlsEx, call it properly and test the return value.

Cheers,

Zooba :U

ic2

Believe it or not I had the same question to myself yesterday and founded this thread...

http://www.masm32.com/board/index.php?topic=3408.0

Quotebut it's still included in the import table, and the dll get's loaded during the startup