Hello there, me again!
Just working through some examples - and I was playing around with this tutorial here http://win32assembly.programminghorizon.com/tut8.html
Anyways so I wrote up the resource file in notepad++ and it seems to all compile and link okay - except that .exe doesn't have any menus!
This got me wondering how masm determines what resource file to use and where it's explicitly referenced in the asm file and how do I ensure that it is actually calling it correctly. I get that I can type the resource file and it shows the proper resource file when i link the obj file - I'm not sure as to exactly how it knows which one to look for. Are there naming conventions that I should observe? Anything else I should watch out for.
#define IDM_TEST 1
#define IDM_HELLO 2
#define IDM_GOODBYE 3
#define IDM_EXIT 4
FirstMenu
{
POPUP "&PopUp"
{
MENUITEM "&Say Hello", IDM_HELLO
MENUITEM "Say &Goodbye", IDM_GOODBYE
MENUITEM SEPARATOR
MENUITEM "E&xit", IDM_EXIT
}
MENUITEM "&Test", IDM_TEST
}
.386
.model flat, stdcall
option casemap :none
WinMain proto :DWORD, :DWORD, :DWORD, :DWORD
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
.data
ClassName db "SimpleWinClass", 0
AppName db "Our First Window", 0
MenuName db "FirstMenu", 0
Test_string db "You selected Test menu item", 0
Hello_string db "Hello, my friend", 0
Goodbye_string db "See you again, bye", 0
.data?
hInstance HINSTANCE ?
CommandLine LPSTR ?
.const
IDM_TEST equ 1
IDM_HELLO equ 2
IDM_GOODBYE equ 3
IDM_EXIT equ 4
.code
start:
invoke GetModuleHandle, NULL
mov hInstance, eax
invoke GetCommandLine
mov CommandLine, eax
invoke WinMain, hInstance, NULL, CommandLine, SW_SHOWDEFAULT
invoke ExitProcess, eax
WinMain proc hInst:HINSTANCE, hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG
LOCAL hwnd:HWND
mov wc.cbSize,SIZEOF WNDCLASSEX
mov wc.style, CS_HREDRAW or CS_VREDRAW
mov wc.lpfnWndProc, OFFSET WndProc
mov wc.cbClsExtra,NULL
push hInst
pop wc.hInstance
mov wc.hbrBackground,COLOR_WINDOW+1
mov wc.lpszMenuName,OFFSET MenuName
mov wc.lpszClassName,OFFSET ClassName
invoke LoadIcon, NULL, IDI_APPLICATION
mov wc.hIcon,eax
mov wc.hIconSm,eax
invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax
invoke RegisterClassEx, addr wc
invoke CreateWindowEx,NULL, ADDR ClassName, ADDR AppName,\
WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\
hInst,NULL
mov hwnd, eax
invoke ShowWindow, hwnd, SW_SHOWNORMAL
invoke UpdateWindow, hwnd
.WHILE TRUE
invoke GetMessage, ADDR msg, NULL,0,0
.BREAK .IF(!eax)
invoke DispatchMessage, ADDR msg
.ENDW
mov eax,msg.wParam
ret
WinMain endp
WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
.IF uMsg==WM_DESTROY
invoke PostQuitMessage, NULL
.ELSEIF uMsg==WM_COMMAND
mov eax, wParam
.IF ax==IDM_TEST
invoke MessageBox,NULL,ADDR Test_string,OFFSET AppName,MB_OK
.ELSEIF ax==IDM_HELLO
invoke MessageBox, NULL, ADDR Hello_string, OFFSET AppName,MB_OK
.ELSEIF ax==IDM_GOODBYE
invoke MessageBox,NULL,ADDR Goodbye_string, OFFSET AppName, MB_OK
.ELSE
invoke DestroyWindow,hWnd
.ENDIF
.ELSE
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.ENDIF
xor eax,eax
ret
WndProc endp
end start
I've included my code just in case i've made an obvious error (it's something like 35C here at 12am so forgive me if I've missed something) - obviously I've missed something - just curious on where to start looking.
Muchos gracias!
\Masm32\examples\exampl01\comctls\comctls.asm - look for SetMenu
in the original example, the menu is supposed to be in the registered class, Jochen
generally, i use LoadMenu, and pass the handle to CreateWindowEx
so, i don't remember the specifics of registering a class with a menu
the info for WNDCLASSEX might help
for lpszMenuName, you might try the ordinal number of the resource, rather than a pointer to a name string
the lpsz method is probably intended for a C compiler
QuotelpszMenuName
Type: LPCTSTR
Pointer to a null-terminated character string that specifies the resource name of the class menu, as the name appears in the resource file. If you use an integer to identify the menu, use the MAKEINTRESOURCE macro. If this member is NULL, windows belonging to this class have no default menu.
also, i'm not sure the menu is properly defined in the example RC file
well, i've never done one that way - i always use an ordinal number like this...
#define IDM_MENU 10
IDM_MENU MENU
POPUP.....
then, in the asm source...
IDM_MENU EQU 10
mov wc.lpszMenuName,IDM_MENU
you can use MENU or MENUEX
in the masm32\bin folder is a help file for RC's (rc.hlp i think)
there are also several examples in the masm32\examples folder
Quote from: dedndave on February 26, 2016, 12:22:24 AM
in the original example, the menu is supposed to be in the registered class, Jochen
comctls.asm
is the original example. And it works, like all examples in \Masm32\examples
btw how do you pass the LoadMenu result to CreateWindowEx?
he's using an example from WinAsm or someone :P
the third from last argument can be a menu handle
i rarely use SetMenu - i did it a couple times when i started playing with windows, i guess
HWND WINAPI CreateWindowEx(
_In_ DWORD dwExStyle,
_In_opt_ LPCTSTR lpClassName,
_In_opt_ LPCTSTR lpWindowName,
_In_ DWORD dwStyle,
_In_ int x,
_In_ int y,
_In_ int nWidth,
_In_ int nHeight,
_In_opt_ HWND hWndParent,
_In_opt_ HMENU hMenu,
_In_opt_ HINSTANCE hInstance,
_In_opt_ LPVOID lpParam
);
Quote from: dedndave on February 26, 2016, 12:29:02 AM
also, i'm not sure the menu is properly defined in the example RC file
#define IDM_MENU 10
IDM_MENU MENU
POPUP.....
then, in the asm source...
IDM_MENU EQU 10
mov wc.lpszMenuName,IDM_MENU
you can use MENU or MENUEX
in the masm32\bin folder is a help file for RC's (rc.hlp i think)
there are also several examples in the masm32\examples folder
https://support.microsoft.com/en-us/kb/917607
Just throws me to https://support.microsoft.com/en-us/kb/917607 - goddamnit windows 10.
So anyways I decided to cheat and use the guys example code. It doesn't bring up the menu either! Is this possibly a win10 issue?
Also I caught where I had forget to define FirstMenu MENU in the rc. I'm going to try some example code. I just try and stick with one tutorial tree to avoid getting lost.
http://imgur.com/clyiYqe this is the final result. So I cannot help but feel that I'm missing something here.
[edit] example loads up menus fine - although the code is a bit crowded so there's stuff in there I don't really understand what its doing if you know what I mean - just wanting to start from the very basics then work up.
a simple example i created for Jack, a while ago...
http://masm32.com/board/index.php?topic=4354.msg46732#msg46732 (http://masm32.com/board/index.php?topic=4354.msg46732#msg46732)
Thanks for that Dave - that looks a bit daunting compared to where I was at, with custom includes and the ilk, but I'll give it a crack.
I think what I'm going to do is basically write a similar application from scratch but copying from your app, the example jj quoted and the tutorial. Hopefully by writing it all myself I can get a better handle on how it all fits together.
Attached a template for a modest Masm32 only window.
(note the *.asc file is for use with MasmBasic's RichMasm editor; it contains a resource section that gets exported by the editor during assembly, i.e. you can edit the resources as if they were part of the main source)
Hey just a quick heads up, I opened that comctls example and after looking at the rc I noticed that it too does not have any menus!
Forgive me if I am wrong but this should have a file/help/about menu if I am not mistaken?
http://imgur.com/RQY3eY0
Should there not be the traditional menu bar across the top?
Also thank you guys very much for fast and prompt response - it means a lot. The human interaction element really helps the learning process and is something I often underutilise.
[edit] thanks JJ that one shows the mnu - I share start tearing this one up now.
it has a toolbar - no menu needed, really
Hey guys I realised I'm a bit of an idiot (well didn't we all) but I think the problem is because I havent actually compiled the resource file!
So I tried using rc.exe and cvtres but they dont seem to have path to the dir where I am building trhe application.
So the file structure looks like A:\masm32\workspace\programfolder
I read there were some issues using the global environment variables for allowing pathing access - that it can interfere with other compilers. So what is the best way to go about compiling the .rc file from rc to .res in this instance (simply trying to use rc. or res gives me bad command or file name). Can i compile the res file in the bin directory or root directory then move it to the workspace folder or will that cause the linker to 'lose sight' of it?
I had a look at this thread here http://masm32.com/board/index.php?topic=327.0
QuoteHi Jannes,
You use the linker, either as a RES file or after converting it to an OBJ file with CVTRES.EXE. For the RES file or the extra OBJ file you need to add it to the object file list on the command line.
Use a command line like this.
\masm32\BIN\Link.exe /SUBSYSTEM:WINDOWS mangled.obj rsrc.obj
But it seems I've got to compile the resource file first ...
Anyways thanks again for the help!
If you are using a batch file, name your rc "MyName.rc" and add this:
IF EXIST MyName.rc \masm32\bin\rc MyName.rc
(if you are using RichMasm, the editor will do it for you)
I'm not using a batchfile (is that a makefile?).
Just doing an asm and a .rc
Supposedly there's a way to compile them in visual studio but i got tired of searching through it trying to find out how. I end up getting distracted by learning the tool rather than just learning the task at hand :(
Quote from: Anaryl on March 07, 2016, 10:19:34 PMSupposedly there's a way to compile them in visual studio
So you are using VS? That explains your difficulties.
Open \Masm32\qeditor.exe and look at the Project menu.
In Visual Studio remember to add your .rc files into project Recource Files
compile with vs
http://masm32.com/board/index.php?topic=4489.msg47997#msg47997
With a batch (Dos,a black screen):
http://stackoverflow.com/questions/9760663/compile-and-run-assembly-file-using-masm-and-context
More questions ?,post a zip file with your working directory.
I was using masm/qeditor but that throws an error
http://imgur.com/F0LrhA1
Then I read it has to be compiled form an rc to a res first?
i'll check those links presently.
it wouldnt let me attach the zip to the last post so i'm trying it here.
RegisterClassEx() missing?
just rename your resource file to what RC wants
Quote from: Anaryl on March 08, 2016, 02:42:34 AM
I was using masm/qeditor but that throws an error
http://imgur.com/F0LrhA1
Then I read it has to be compiled form an rc to a res first?
It doesn't hurt to read the error messages: "could not open rsrc.rc" is a very valuable hint IMHO 8)
Quote from: jj2007 on March 08, 2016, 04:11:28 AM
Quote from: Anaryl on March 08, 2016, 02:42:34 AM
I was using masm/qeditor but that throws an error
http://imgur.com/F0LrhA1
Then I read it has to be compiled form an rc to a res first?
It doesn't hurt to read the error messages: "could not open rsrc.rc" is a very valuable hint IMHO 8)
I tried that - same error.
http://imgur.com/prt5svl
So what is your theory why rc.exe can't open rsrc.rc?
I have three:
- you forgot to create rsrc.rc
- it's not in the main source's path
- it's open in another application (Visual Crap?), so access denied.
8)
My theory is that it needs to specifically compiled by the rc.exe and that for some reason qeditor can't path rc.exe to the masm32\workspace directory.
I've checked the other ones. I failed at compiling the .rc file before I reinstalled VS so it's not that (but obviously double checked) and it's not failed to create rsrc.rc because when the error came up that seemed like an obvious first step to try (but again I just double checked this).
The thing iwth the pathing though is that the .asm and run program all run fine from qeditor/masm32 - and it works fine with example code (it's basically a rewrite/rubberduck of exeample01\generic\generic.asm - and that code works and compiles perfectly.
So my theory is that rc.exe is either not pathing correctly or I am a noob and have mssed something obvious.
Quote from: Anaryl on March 08, 2016, 05:53:53 AM
My theory is that it needs to specifically compiled by the rc.exe and that for some reason qeditor can't path rc.exe to the masm32\workspace directory.
Which app produces error RC 1234?
Seriously: check my three theories above. Obviously, qEditor finds rc.exe, otherwise no RC nnnn errors. It does not find rsrc.rc, though. More precisely, it cannot
open rsrc.rc. Does this file exist, and if yes, in which folder? The same as mysource.asm? If the file exists and is in the right folder, it might be open in Visual Crap, so be sure you close that one completely.
If nothing helps, install MasmBasic (http://masm32.com/board/index.php?topic=94.0), open your source in \Masm32\MasmBasic\RichMasm.exe and hit F6. If you have errors, copy the output window's content and post it here.
I gotta admit I was starting to get a bit frustrated here (probably not helped by an impending tobacco scarcity), But your tool actually helped me out here!
** Start A:\Masm32\MasmBasic\Res\bldallRM.bat
***** user-defined OPT_xx variables: ***
*** anawin2.rc not found, will try rsrc.rc ***
OPT_Arg1:
OPT_Arg2:
OPT_Out: "anawin2.exe"
OPT_Res: rsrc
*** Assemble, link and run anawin2 ***
rsrc.rc (1): error RC2135 : file not found: MAINICON.ICO
*** Resource "rsrc.rc" could not be created ***
So what seemed to be the problem was the call for Mainicon.ico (a relic from copying and pasting the .rc from the generic dir).
After removing the .ico file
** Start A:\Masm32\MasmBasic\Res\bldallRM.bat
***** user-defined OPT_xx variables: ***
OPT_Arg1:
OPT_Arg2:
OPT_Out: "anawin2.exe"
OPT_Res: anawin2
*** Assemble, link and run anawin2 ***
*** Assemble using JWasm /c /coff /Fl /Sn /Fo "anawin2" ***
JWasm v2.12pre, Feb 18 2014, Masm-compatible assembler.
Portions Copyright (c) 1992-2002 Sybase, Inc. All Rights Reserved.
Source code is available under the Sybase Open Watcom Public License.
***********
ASCII build
***********
Tmp_File.asm: 284 lines, 2 passes, 153 ms, 0 warnings, 0 errors
*** Link using polink with sub WINDOWS "anawin2.obj" rsrc.res /OUT:"anawin2.exe" ***
*** Assembling and linking took 281 milliseconds ***
03/08/2016 07:50 PM 3,072 anawin2.exe
03/08/2016 07:50 PM 2,203 anawin2.obj
03/08/2016 07:50 PM 218 anawin2.rc
03/06/2016 02:54 AM 10,567 anawin2.asm
« OK »** RichMasm warning: Exit code 'still active' **
Output returned when trying to link and run
***********
ASCII build
***********
Tmp_File.asm: 284 lines, 2 passes, 171 ms, 0 warnings, 0 errors
*** Link using polink with sub WINDOWS "anawin2.obj" rsrc.res /OUT:"anawin2.exe" ***
POLINK: fatal error: Access is denied.
*** Link error ***
Hmmm okay? Check taskman - the application still seems to have been running there. Kill those processes from before.
Try again.
Okay so it seems now that the application doesn't create a window at all now ...
Hmm, alright well at least the .rc compiles ... so back to the drawing board.
[edit] was able to use the Masm editor you linked to get it to compile the code effectively and get it to run straight away.
So my take away here is - why doesn't qeditor automatically compile the rc files? It seems to have permissions issues over actually compiling them. I'm going to fiddle around again with it to see whats causing it. At least now I know the code works.
RegisterClassEx() still missing from that code?
Bad WNDCLASSEX
mov wc.cbSize,sizeof WNDCLASSEX
mov wc.style,CS_BYTEALIGNCLIENT or CS_BYTEALIGNWINDOW
m2m wc.lpfnWndProc, WndProc
mov wc.cbClsExtra, NULL ;obsolete voir API SetProp
mov wc.cbWndExtra, NULL
Push hInstance
pop wc.hInstance
invoke LoadIcon,NULL,IDI_HAND
mov wc.hIcon,eax
invoke LoadCursor, NULL, IDC_ARROW ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
mov wc.hCursor,eax
m2m wc.hbrBackground, COLOR_BTNFACE+1
mov wc.lpszMenuName,NULL
mov wc.lpszClassName, offset szClassName
mov wc.hIconSm,0
invoke RegisterClassEx, ADDR wc
bad WM_CLOSE
.elseif uMsg == WM_CLOSE
;---------------------------------------------
; this is the place where various requirements are performed before the app exits to the OS
; such as deleting resources and testing if files have been saved. You have the option of returning
; ZERO if you dont wish the application to close which exits the WndProce procedure without passi
; this messages to the defgault window processing done by the OS
;---------------------------------------------
szText TheText, "Please Confirm Exit"
invoke MessageBox, hWin, ADDR TheText, ADDR szDisplayName,MB_YESNO
.if eax == IDNO
return 0
.endif
invoke PostMessage,hWin,WM_DESTROY,0,0
.elseif uMsg == WM_DESTROY
Okay, so I got it to work.
It seemed that the trick required was to give rc.exe admin privileges and rename the resource file to rsrc.rc then > assemble asm >compile resource file >link obj > run program.
In regards to the previous post
I took the code from here http://www.programminghorizon.com/win32assembly/tut8.html and whilst it is all well and good to say "This code is bad" may I trouble you to ask
why is it bad?
[edit] I somehow broke it again.
Quote** Start A:\masm32\MasmBasic\Res\bldallRM.bat
***** user-defined OPT_xx variables: ***
*** anawin3.rc not found, will try rsrc.rc ***
OPT_Arg1:
OPT_Arg2:
OPT_Out: "anawin3.exe"
OPT_Res: rsrc
*** Assemble, link and run anawin3 ***
*** Resource "rsrc.rc" could not be created ***
So I decided I would just start modifying the files and poking around. But for some reason it broke it again. Going to keep messing with it.
Aha so it just wont compile at all in event of syntax errors. Well still I have learned something now.
So my next question is do I always have to call .rc files rsrc?
Quote from: Anaryl on March 08, 2016, 11:39:04 PMAha so it just wont compile at all in event of syntax errors.
Yes, that is normal behaviour.
QuoteSo my next question is do I always have to call .rc files rsrc?
Depends on the editor/IDE. RichMasm, for example,
- checks if anawin3.rc exists; if no, if rsrc.rc exists; if one of them is present, rc.exe will be called before linking;
- examines the code for "Windows" keywords such as Load, WM_CREATE etc, then for "console" keywords such as print, inkey, StdOut, and instructs the linker to use the appropriate subsystem.
etc...
I don't think you need admin rights for rc.exe (I never needed them). Your problem seems to be that no window is created, due to the missing RegisterClassEx. In RichMasm, click on File/New Masm source, then pick Simple window (
Masm32) from the templates. It has all you need for creating a simple window. Besides, at the end of the file you can edit the resources, too - the rc file gets created when you hit F6 to build the project.
Note: If after a successful build (no assembly, linker or rc errors) you get "access denied", the reason may be that a windows application hangs in an endless loop somewhere (missing RegisterClassEx...). In RichMasm, one way to test this is to put, at the end of the code, OPT_Susy Console to force subsystem console. Then, you can insert print "creating main window" or whatever debugging message you need to find out where exactly it hangs.
************So my next question is do I always have to call .rc files rsrc?****************
You choose the name you want for the rc file,.txt if you want,this work.
The only rule is that the linker must find it when he assemble the module .
link ........ asm.obj Myresource.bin ;for example.
To compile a rc file you need those two progs:
Rc.exe /v %FILE%.rc
Cvtres.exe /machine:ix86 /out:%FILE%.bin %FILE%.res
the /out: of cvtres allow you to name it as you want.
Here is a batch file for training,the anawin1 play with names
Thanks for that Tout, I will start playing around with them now. I'm starting to get my head around the res compilation. Still seems a bit fiddly at times where I am like reloading the file or editor to get it to work but I think I am getting the hang of it.
I will have a play around with these now so I can get a better handle (ahem) on the language and concepts therein. Thanks heaps for the help you guys.