I have always liked the technique but have not done much with it for some years. I did the original set of macros back in the Win88 days when it was genuine PHUN to debug, they are much easier to work with in development from Win2000 upwards. I am tempted to upgrade this set of techniques as it provides a fully self contained dialog capacity that does not use resource dialogs at all and has all the advantages of a scalable yet precision interface where you don't go blind and mad trying to line up controls in a dialog editor.
I have attached a test piece that takes ANSI strings. There are a number of ways of handling UNICODE strings, resource strings being the older technique but they can be stored as byte sequences and passed by address to UNICODE API functions for languages like Chinese and Japanese.
I think there is a viable method to do much the same with image data, store it as byte data, load it into a temporary file, read that file with LoadImage() then delete the file. The tests so far have been good and easily fast enough so if it looks like it viable, it would be easy enough to make a tool that loads the image file as DB data so the function can be called and return either a valid ICO or BMP handle from that data.
There is no need to create a temporary file with image data, you can convert an area of memory directly to a DIB. You simply have to create an empty DIB then use SetDIBits (http://msdn.microsoft.com/en-us/library/dd162973%28v=vs.85%29.aspx) to read the transfer into the image. Much faster using the disk drive. If you have stored the full image the header can give you all the information you need to rebuild the DIB (color table etc...) even conversion to/from different palettes is fairly simple. Pretty sure I wrote a function to do it (in MASM it was that long ago) I'll have a peek at the old archives.
Thanks Edgar, I would certainly be interested to see it. I wasted the time playing with CreateBitmapIndirect() but could not get it to work in a static control where the handle returned by CreateImage() works perfectly. If you create a temporary file using that flag the OS retains it in memory unless it is very large so the read back time with CreateImage is reasonably fast, the same technique can be used with an icon as well.
Hi Steve,
The archives are on DVDs and contain thousands of compressed projects/tools etc.. it will take a day or two. It should do icons as well, at any rate bitmap to icon conversion is pretty simple, I have many examples of how to do that.
I found one for icons held in data, its in GoAsm syntax though, translated on the fly (sorry about the square brackets I know you hate them :P) :
CreateIconFromData PROC pIconData:DWORD, iIcon:DWORD
LOCAL sz[2] :DWORD
/*
CreateIconFromData
Creates an icon from icon data stored in the DATA or CONST SECTION
(The icon data is an ICO file stored directly in the executable)
Parameters
pIconData = Pointer to the ico file data
iIcon = zero based index of the icon to load
If successful will return an icon handle, this handle must be freed
using DestroyIcon when it is no longer needed. The size of the icon
is returned in EDX, the high order word contains the width and the
low order word the height.
Returns 0 if there is an error.
If the index is greater than the number of icons in the file EDX will
be set to the number of icons available otherwise EDX is 0. To find
the number of available icons set the index to -1
*/
xor eax, eax
mov edx, [pIconData]
or edx, edx
jz ERRORCATCH
movzx eax, WORD PTR [edx+4]
cmp eax, [iIcon]
ja @F
ERRORCATCH:
push eax
invoke SetLastError, ERROR_RESOURCE_NAME_NOT_FOUND
pop edx
xor eax, eax
ret
@@:
mov eax, [iIcon]
shl eax, 4
add edx, eax
add edx, 6
movzx eax, BYTE PTR [edx]
mov [sz], eax
movzx eax, BYTE PTR [edx+1]
mov [sz+4], eax
mov eax, [edx+12]
add eax, [pIconData]
mov edx, [edx+8]
invoke CreateIconFromResourceEx, eax, edx, 1, 030000h, [sz], [sz+4], 0
mov edx,[sz]
shl edx,16
mov dx,[sz+4]
RET
CreateIconFromData endp
Hi Hutch,
Here is a quick example to convert an image in memory to bitmap :
; On success, the function returns the handle to the bitmap otherwise it returns 0
.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\gdi32.inc
.code
CreateBmpFromMem PROC hWnd:DWORD,pBmp:DWORD
LOCAL hDC:DWORD
LOCAL hBmp:DWORD
invoke GetDC,hWnd
test eax,eax
jz @f
mov hDC,eax
mov edx,pBmp
lea ecx,[edx + SIZEOF BITMAPFILEHEADER] ; start of the BITMAPINFOHEADER header
mov eax,BITMAPFILEHEADER.bfOffBits[edx]
add edx,eax
invoke CreateDIBitmap,hDC,ecx,CBM_INIT,edx,ecx,DIB_RGB_COLORS
mov hBmp,eax
invoke ReleaseDC,hWnd,hDC
mov eax,hBmp
@@:
ret
CreateBmpFromMem ENDP
END
Edgar, Erol,
Thank you both, its been years since I have done this stuff and i am a long way out of practice.
LATER : I have tested Erol's algo and it works fine, problem is it displays the alpha channel in an RGB/a bitmap as a black background. Rough guess here is that the later structure BITMAPV5HEADER appears to have the alpha channel data but I am just in the process of decyphering it. :P
LATER AGAIN : That problem solved, must have a manifest file to get the alpha channel to be transparent.
This is the working example of what I was after with both Erol's algo and the disk based on the uses LoadImage(). The direct memory load should be a lot faster but the LoadImage() version is a lot more flexible with scaling so I see a use for both.
The next trick I need is a similar algo to load an Icon from memory. LoadImage() does this fine but it may be a speed advantage i some contexts to have a direct memory load version.
Hi Hutch,
With thanks to xandaz's code, I coded an application displaying an icon from memory :
.IF uMsg==WM_INITDIALOG
invoke CreateBmpFromMem,hWnd,ADDR pIcon
mov hBitmap,eax
; Code portion from xandaz
mov ii.fIcon,TRUE
push hBitmap
pop ii.hbmMask
push hBitmap
pop ii.hbmColor
invoke CreateIconIndirect,ADDR ii
mov hIcon,eax
Gratsie,
I will digest this a bit later. I have added a couple of extra controls to play with, basically bitmap and icon versions that use the center image flag, just have to check that they behave in predictable ways. Getting both bitmaps and icons stored directly in code is very useful in that it allows complete object design for components that are fully self contained so they can just be linked and called without having to tweak the details for each use.
Here is a test piece with 2 new macros to handle centered images. The original macros for both icons and bitmaps set the image location to the top left X Y corordinates. This extra pair allow a static control to be placed in an area of a dialog interface and will center any image loaded into them. They will also clip the image if its bigger than the control.
IMPORTANT : The attached ZIP file has the later version of DIALOGS.INC that has the extra two macros in it, replace the old one with this one, everything else is the same.
works fine here, Hutch
XP MCE2005 SP2
(http://img846.imageshack.us/img846/6917/dlgtest.png)
Hi Hutch,
I downloaded your example but it did not work on my XP Pro SP3. Could it be a manifest file issue?
hiyas Erol
did you replace the dialogs.inc file ?
i used the one from the other thread (in the masm32 subforum)
perhaps they are different :P
did it assemble properly ?
Hi Dave,
I replaced the include file. No problem with building the project but running the executable does not display the GUI.
On Win XP SP2, there is indeed a problem with the manifest file:
If it is included in rsrc.rc, the app launches but does not show and quits silently.
If 1 24 "manifest.xml" is removed, it works just fine.
that's odd Jochen - it works here
the only thing "out of the ordinary" that i see in the manifest is the "description" tag
I put
mactst.exe
echo %ERRORLEVEL%
into the batch file. "Impossible to run the specified program" and errorlevel 9020 ::)
With //1 24 manifest.xml commented out in rsrc.rc it runs fine and gives errorlevel 0.
Same problem with an earlier app, if it has a manifest file it must have the common controls enabled. This may be specific to the Windows version that Erol is running but it looks like you need both to be safe on all Windows versions.
The attached ZIP file has the modification done by enabling the common control library.
i am curious to see if this one runs on your machine JJ...
Hutch 1:0 Dave
:bg
heeyyyyyyyyyyyyyyyyyy
i just wanted to know if i will see the problem on my machine :bg
Dave,
Probably not if you are running a US version of XP but for folks writing general purpose software its worth knowing that you need both a manifest file AND that you must enable the common controls to display the later styles for XP, Vista and Win7.
The feedback from both Erol and JJ has been very useful.
It seem, that nobody, except Hutch and Vortex, ever reading my useless posts: http://www.masm32.com/board/index.php?topic=15932.msg131804#msg131804
Sadly enough :(
hiyas Alex :U
well - the wording is a little hard to understand in that post :P
noone mentioned it had to do with language/versions of XP, either - until now
i thought it might be something to do with the fact that i have media center edition - lol
there are a couple very hefty updates for MCE that do not get installed onto regular XP
as i recall, one is 20 Mb and the other is 35 Mb
Quote from: dedndave on March 18, 2011, 03:35:19 AM
hiyas Alex :U
well - the wording is a little hard to understand in that post :P
noone mentioned it had to do with language/versions of XP, either - until now
i thought it might be something to do with the fact that i have media center edition - lol
there are a couple very hefty updates for MCE that do not get installed onto regular XP
as i recall, one is 20 Mb and the other is 35 Mb
Well, then I'll write in native language :P
:bg
Alex,
I have no doubt that many read you post, its just that I remembered it. :U
Hi,
It works fine on Windows 7 (both 32 and 64-bit), but it doesn't on Windows XP SP3.
Alex had the right idea. See attachment, and try the UseCommonControls option...
OK,
So if I have it right at the moment, some Windows versions are conditional in their usage of the initialised common control library. With the US English versions I use this code works on all of them, Win2000, XP SP3 and Win7 64 bit. I looked at the mod that JJ posted which runs on my US English versions. Now the situation that Erol reported was that on his Windows version if you ran a manifest file without enabling the common control library that the dialog would not start.
Now what I am interested in determining is if on some Windows language versions that you must match the control flags to the controls used. IE bar classes for toolbars and status bars etc ...
mov icce.dwSize, SIZEOF INITCOMMONCONTROLSEX
xor eax, eax
or eax, ICC_ANIMATE_CLASS
or eax, ICC_BAR_CLASSES
or eax, ICC_COOL_CLASSES
or eax, ICC_DATE_CLASSES
or eax, ICC_HOTKEY_CLASS
or eax, ICC_INTERNET_CLASSES
or eax, ICC_LISTVIEW_CLASSES
or eax, ICC_PAGESCROLLER_CLASS
or eax, ICC_PROGRESS_CLASS
or eax, ICC_TAB_CLASSES
or eax, ICC_TREEVIEW_CLASSES
or eax, ICC_UPDOWN_CLASS
or eax, ICC_USEREX_CLASSES
or eax, ICC_WIN95_CLASSES
mov icce.dwICC, eax
invoke InitCommonControlsEx,ADDR icce
yikes !
how about.....
ICC_FLAGS = ICC_WIN95_CLASSES
ICC_FLAGS = ICC_FLAGS or ICC_ANIMATE_CLASS
ICC_FLAGS = ICC_FLAGS or ICC_BAR_CLASSES
ICC_FLAGS = ICC_FLAGS or ICC_COOL_CLASSES
ICC_FLAGS = ICC_FLAGS or ICC_DATE_CLASSES
ICC_FLAGS = ICC_FLAGS or ICC_HOTKEY_CLASS
ICC_FLAGS = ICC_FLAGS or ICC_INTERNET_CLASSES
ICC_FLAGS = ICC_FLAGS or ICC_LISTVIEW_CLASSES
ICC_FLAGS = ICC_FLAGS or ICC_PAGESCROLLER_CLASS
ICC_FLAGS = ICC_FLAGS or ICC_PROGRESS_CLASS
ICC_FLAGS = ICC_FLAGS or ICC_TAB_CLASSES
ICC_FLAGS = ICC_FLAGS or ICC_TREEVIEW_CLASSES
ICC_FLAGS = ICC_FLAGS or ICC_UPDOWN_CLASS
ICC_FLAGS = ICC_FLAGS or ICC_USEREX_CLASSES
.DATA
icc INITCOMMONCONTROLSEX <sizeof INITCOMMONCONTROLSEX,ICC_FLAGS>
.CODE
INVOKE InitCommonControlsEx,offset icc
total size ~ 18 bytes
Hutch - i doubt there is any harm in initializing controls you don't use
although, it may use memory unnecessarily
the problem i see is that if you don't initialize the ones you do use....
.... it has to be tested on a platform that exhibits the problem :'(
Dave,
Apart from the MASM line length limit there is nothing to stop you from orring the whole lot together so that you only had 4 bytes but size is not the problem, I am trying to quantify why initialising all of the controls works on some Windows versions but not others and by versions I mean the language version. I cannot duplicte the problem with any of my US English versions.
I have the OR list for convenience of being able to comment them in and out, not for minimum size even though their memory usage is trivial.
that's why i listed them seperately, as well - so you can comment them out
i see a lot of uninitialied structures - initialized in code
if you initialize a dword in code, it usually takes at least 5 bytes :dazzled:
why not just pre-initialize the data - execution time = 0 - and it is smaller
(it might make sense if much of the structure need not be initialized)
Quote from: hutch-- on March 18, 2011, 04:00:49 AM
Alex,
I have no doubt that many read you post, its just that I remembered it. :U
Thank you, Hutch! :bg
Dave,
The assumption that the size matters is one we don't share, this type of stuff most probably would not line up to the next 512 byte section. I am far more interested in getting it to work on multiple language versions.
Jochen:
call InitCommonControlsEx ; this will never be called, but
:wink this is right, the dll just should be statically linked. On my system InitCommonControls code is just a RET as first instruction of the "function". Very funny.
What it is on other systems?
Hi Hutch,
Thanks for the new version of the example. It works fine. InitCommonControls solved the problem.
Hi Antariy,
I remembered for your posting, thanks.
Hi Hutch,
This is my report for catalan and spanish versions of Windows:
Win2K3 Server and Win7 32-64 bit: The dialog works fine without initializing common controls.
WinXp SP3: The dialog just works if common controls are initialized. However, calling InitCommonControls is enough (no need to call InitCommonControlsEx).
Regards.
Quote from: Antariy on March 18, 2011, 02:10:24 PM
:wink this is right, the dll just should be statically linked. On my system InitCommonControls code is just a RET as first instruction of the "function". Very funny.
What it is on other systems?
Win XP SP2, Italian edition: InitCommonControls is just a
retn, and static linking without actually calling it makes the dialog work ::)
InitCommonControls
Ex has the same positive effect, but when you call it, there is a bit more than just a retn. It starts with the intelligent opcode
mov edi, edi ;-)
perhaps there is more to it than meets the eye
it may be that pulling the function in also pulls in some other code and/or data that is not readily obvious