The MASM Forum Archive 2004 to 2012

Project Support Forums => MASM32 => Topic started by: hutch-- on March 15, 2011, 01:09:53 PM

Title: Memory dialogs revisited.
Post by: hutch-- on March 15, 2011, 01:09:53 PM
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.
Title: Re: Memory dialogs revisited.
Post by: donkey on March 15, 2011, 01:46:25 PM
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.
Title: Re: Memory dialogs revisited.
Post by: hutch-- on March 15, 2011, 02:07:00 PM
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.
Title: Re: Memory dialogs revisited.
Post by: donkey on March 15, 2011, 02:10:08 PM
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.
Title: Re: Memory dialogs revisited.
Post by: donkey on March 15, 2011, 02:47:57 PM
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
Title: Re: Memory dialogs revisited.
Post by: Vortex on March 15, 2011, 08:32:30 PM
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
Title: Re: Memory dialogs revisited.
Post by: hutch-- on March 15, 2011, 10:56:39 PM
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.
Title: Re: Memory dialogs revisited.
Post by: hutch-- on March 16, 2011, 05:34:44 AM
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.
Title: Re: Memory dialogs revisited.
Post by: Vortex on March 16, 2011, 09:19:07 PM
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

Title: Re: Memory dialogs revisited.
Post by: hutch-- on March 17, 2011, 12:06:43 AM
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.
Title: Re: Memory dialogs revisited.
Post by: hutch-- on March 17, 2011, 04:27:34 AM
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.
Title: Re: Memory dialogs revisited.
Post by: dedndave on March 17, 2011, 10:57:15 AM
works fine here, Hutch

XP MCE2005 SP2

(http://img846.imageshack.us/img846/6917/dlgtest.png)
Title: Re: Memory dialogs revisited.
Post by: Vortex on March 17, 2011, 07:31:19 PM
Hi Hutch,

I downloaded your example but it did not work on my XP Pro SP3. Could it be a manifest file issue?
Title: Re: Memory dialogs revisited.
Post by: dedndave on March 17, 2011, 08:17:47 PM
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 ?
Title: Re: Memory dialogs revisited.
Post by: Vortex on March 17, 2011, 09:59:28 PM
Hi Dave,

I replaced the include file. No problem with building the project but running the executable does not display the GUI.
Title: Re: Memory dialogs revisited.
Post by: jj2007 on March 17, 2011, 10:53:59 PM
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.
Title: Re: Memory dialogs revisited.
Post by: dedndave on March 17, 2011, 10:57:14 PM
that's odd Jochen - it works here
the only thing "out of the ordinary" that i see in the manifest is the "description" tag
Title: Re: Memory dialogs revisited.
Post by: jj2007 on March 17, 2011, 11:06:18 PM
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.
Title: Re: Memory dialogs revisited.
Post by: hutch-- on March 17, 2011, 11:14:03 PM
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.
Title: Re: Memory dialogs revisited.
Post by: dedndave on March 17, 2011, 11:14:18 PM
i am curious to see if this one runs on your machine JJ...
Title: Re: Memory dialogs revisited.
Post by: jj2007 on March 17, 2011, 11:37:26 PM
Hutch 1:0 Dave
:bg
Title: Re: Memory dialogs revisited.
Post by: dedndave on March 17, 2011, 11:39:32 PM
heeyyyyyyyyyyyyyyyyyy
i just wanted to know if i will see the problem on my machine   :bg
Title: Re: Memory dialogs revisited.
Post by: hutch-- on March 18, 2011, 12:59:53 AM
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.
Title: Re: Memory dialogs revisited.
Post by: Antariy on March 18, 2011, 03:20:18 AM
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 :(
Title: Re: Memory dialogs revisited.
Post by: 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
Title: Re: Memory dialogs revisited.
Post by: Antariy on March 18, 2011, 03:44:47 AM
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
Title: Re: Memory dialogs revisited.
Post by: 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
Title: Re: Memory dialogs revisited.
Post by: Ramon Sala on March 18, 2011, 08:13:07 AM
Hi,

It works fine on Windows 7 (both 32 and 64-bit), but it doesn't on Windows XP SP3.
Title: Re: Memory dialogs revisited.
Post by: jj2007 on March 18, 2011, 10:51:25 AM
Alex had the right idea. See attachment, and try the UseCommonControls option...
Title: Re: Memory dialogs revisited.
Post by: hutch-- on March 18, 2011, 12:59:27 PM
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 ...
Title: Re: Memory dialogs revisited.
Post by: dedndave on March 18, 2011, 01:03:08 PM
   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   :'(
Title: Re: Memory dialogs revisited.
Post by: hutch-- on March 18, 2011, 01:31:05 PM
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.
Title: Re: Memory dialogs revisited.
Post by: dedndave on March 18, 2011, 01:35:04 PM
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)
Title: Re: Memory dialogs revisited.
Post by: Antariy on March 18, 2011, 01:56:26 PM
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
Title: Re: Memory dialogs revisited.
Post by: hutch-- on March 18, 2011, 02:07:49 PM
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.
Title: Re: Memory dialogs revisited.
Post by: Antariy on March 18, 2011, 02:10:24 PM
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?
Title: Re: Memory dialogs revisited.
Post by: Vortex on March 18, 2011, 06:49:52 PM
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.
Title: Re: Memory dialogs revisited.
Post by: Ramon Sala on March 18, 2011, 07:39:18 PM
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.
Title: Re: Memory dialogs revisited.
Post by: jj2007 on March 18, 2011, 07:53:08 PM
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 ::)
InitCommonControlsEx 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 ;-)
Title: Re: Memory dialogs revisited.
Post by: dedndave on March 18, 2011, 11:24:40 PM
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