Been toying with your snippets for a while... this is the result.
Two issues:

1. Since we're using the get_Handle method to get the bitmap (and then copying it), shouldn't we copy the pallete as well?

2. Your function will get the RGB values of the transparent GIF, and AFAIK we should use the pallete entry instead. We might have a repeated color in the pallete, one transparent and the other opaque. That would mess up the transparency. Should be easy to fix as long as the IPicture object does not alter the image's original pallete values.

BTW, my sample prog isn't even loading the picture... don't know why. :confused:


This code works. At some point I would like to have the picture inserted into the .exe instead of in a separate
file.

Thanks.


; showpic.asm File location of jpeg is hardcoded into this
; Includes Image file loading routines for the MASM32 library
;
; This source and assosciated binary code is
; Copyright ? 2001 by M Stoller Enterprises
;
; Written by Ernest Murphy
;
; Not for commercial reproduction. No fee whatsoever may be imposed for
; transfering this file. Source files may be coppied only for educational use
; on a free basis.


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
include \masm32\include\masm32.inc
include \masm32\include\gdi32.inc
include \masm32\include\comctl32.inc
include \masm32\include\ole32.inc
include \masm32\include\oleaut32.inc
include image.inc

includelib \masm32\lib\user32.lib
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\gdi32.lib
includelib \masm32\lib\ole32.lib
includelib \masm32\lib\oleaut32.lib
includelib \masm32\lib\COMCTL32.LIB
includelib image.lib

.data
ClassName db "SimpleWinClass",0
AppName db "Show a non-bmp image",0
OurText db "Win32 Executable - less than 5K too :-) ",0
szFile BYTE "C:\masm32\BIN\german1.jpg",0


.data?
hInstance HINSTANCE ?
CommandLine LPSTR ?
hBmp DWORD ?
.code
start:
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke GetCommandLine
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
mov wc.cbWndExtra,NULL
push hInst
pop wc.hInstance
mov wc.hbrBackground,COLOR_WINDOW+1
mov wc.lpszMenuName,NULL
mov wc.lpszClassName,OFFSET ClassName
invoke LoadIcon,NULL,IDI_APPLICATION
mov wc.hIcon,eax
mov wc.hIconSm,0
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 TranslateMessage, ADDR msg
INVOKE DispatchMessage, ADDR msg
.ENDW
mov eax,msg.wParam
ret
WinMain endp
WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
LOCAL hdc:HDC
LOCAL ps:PAINTSTRUCT
LOCAL rect:RECT
LOCAL tempDC:DWORD
LOCAL htbmp
.IF uMsg==WM_DESTROY
invoke PostQuitMessage,NULL
.ELSEIF uMsg==WM_PAINT
invoke BeginPaint,hWnd, ADDR ps
mov hdc,eax
invoke GetClientRect,hWnd, ADDR rect
invoke DrawText, hdc,ADDR OurText,-1, ADDR rect, DT_SINGLELINE or DT_RIGHT ;or DT_CENTER or DT_VCENTER
invoke CreateCompatibleDC, hdc
mov tempDC, eax
invoke SelectObject, tempDC, hBmp
mov htbmp, eax
invoke BitBlt, hdc, 0,0,rect.right,rect.bottom, tempDC, 0, 0, SRCCOPY
invoke SelectObject, tempDC, htbmp
invoke DeleteDC, tempDC
invoke EndPaint,hWnd, ADDR ps
.ELSEIF uMsg==WM_CREATE
invoke BitmapFromFile, ADDR szFile
; invoke BitmapFromResource, hInstance, 2002
; invoke BitmapFromResource, hInstance, 2001
mov hBmp, eax
.ELSE
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.ENDIF
xor eax,eax
ret
WndProc endp
end start
Posted on 2004-03-02 19:08:08 by skywalker

Been toying with your snippets for a while... this is the result.
Two issues:

1. Since we're using the get_Handle method to get the bitmap (and then copying it), shouldn't we copy the pallete as well?

2. Your function will get the RGB values of the transparent GIF, and AFAIK we should use the pallete entry instead. We might have a repeated color in the pallete, one transparent and the other opaque. That would mess up the transparency. Should be easy to fix as long as the IPicture object does not alter the image's original pallete values.

BTW, my sample prog isn't even loading the picture... don't know why. :confused:


Hi QvasiModo,

1. Since the returned handle is a rendering of the original image (it is not a bitmap after all) the IPicture interface does color correction (ICM) so the palette is not necessarily the same when it is loaded. I found that in my tests when using it in TBPaint that there were some horrible results when saving images loaded and saved with IPicture. Remember the early days of TBPaint when the greens etc.. were darker or lighter than the original. However I think that if you use the IPicture::KeepOriginalFormat method you can bypass this, I have never tried.

2. My GIF transparency thingy actually finds the color by palette index, not by scanning the color table. You can have the index by preserving it from this :

movzx eax,B

EAX contains the palette index, the rest just looks up the color in the color table.

3. I have found that it seems to make no difference on any Windows version if you pass a pointer returned from GlobalAlloc in place of a handle (including all GlobalXXX functions such as GlobalSize etc..), I geuss to be 100% certain you should pass an HGLOBAL instead but the two seem to be interchangeable.
Posted on 2004-03-02 22:41:29 by donkey

3. I have found that it seems to make no difference on any Windows version if you pass a pointer returned from GlobalAlloc in place of a handle (including all GlobalXXX functions such as GlobalSize etc..), I geuss to be 100% certain you should pass an HGLOBAL instead but the two seem to be interchangeable.

My experience as well - and it makes sense, since win32 doesn't use the same handle+lock based system as win16, and all the 'normal' memory allocations end up allocating from the heap (including Global/LocalAlloc).

However, there is a difference between the values returned with and without GMEM_FIXED - somebody with access to the NT source should have a look as to what is going on... :rolleyes: . It might be pedantic of me, but for the sake of safety, I'm doing the extra steps of GlobalLock and such.
Posted on 2004-03-03 04:01:09 by f0dder
No need for the source, the memory is allocated differently and there is no need for a handle at all...

From Managing Heap Memory in Win32
Randy Kath
Microsoft Developer Network Technology Group


It is surprising that the distinction between FIXED and MOVEABLE memory still exists in these functions. In Windows 3.1, MOVEABLE memory compacted the local and global heaps to reduce fragmentation and make more memory available to all applications. Yet the Windows NT virtual memory system does not rely on these techniques for efficient memory management and has little to gain by applications using them. In any case, they still exist and could actually be used in some circumstances.

When allocating FIXED memory in Win32, the GlobalAlloc and LocalAlloc functions return a 32-bit pointer to the memory block rather than a handle as they do for MOVEABLE memory. The pointer can directly access the memory without having to lock it first. This pointer can also be passed to the GlobalFree and LocalFree functions to release the memory without having to first retrieve the handle by calling the GlobalHandle function. With FIXED memory, allocating and freeing memory is similar to using the C run-time functions _malloc and _free.
Posted on 2004-03-03 04:18:49 by donkey
Hmmm... however, that says nothing about

*) What happens if you treat a "handle" (ie, no FIXED flag) return as a pointer?

*) What happens when GlobalLock and, more importantly, GlobalUnlock, are called for a FIXED alloc pointer?

The allocations done by Local/GlobalAlloc are done on the heap, but with some special/undocumented flags appended. It seems that, opposed to a straight HeapAlloc call, the memory region has some 8-byte structure prepended. If you use GMEM_FIXED you get a memory pointer, if you don't, you get a "handle" - which is this structure that's 8 bytes directly before the memory itself.

I haven't looked into what's stored in this structure, but I have the impression that overwriting it "might be bad". This is probably only an issue if you treat a 'handle' as a pointer, and not the other way around - treating a handle as a pointer would overwrite this structure, but functions might have some safechecking to see whether they're operating on pointers or 'handles'.
Posted on 2004-03-03 04:42:18 by f0dder
Mmm,

I thought that the handles were acutally structures stored outside of the heap address space, that is that they are stored in some other location of memory in an table of structures. If you do not create a moveable chunk of memory the handle table is never created and calls to GlobalLock will simply return the same address, making it essentially interchangeable. For example :

invoke GlobalAlloc,GMEM_FIXED,1024

mov [pGlob],eax
invoke GlobalUnlock,[pGlob]
; eax == 1 ; success
invoke GlobalLock,[pGlob]
; eax == pGlob
invoke GlobalFree,[pGlob]


As you can see they are 100% interchangeable, even if a function assumes that you are passing it a handle, it must first lock the memory in order to write to or read from it and that will simply return the same pointer. GlobalUnlock always returns 1 which is correct in this context as the reference count remains locked at one reference. Ofcourse with a fixed reference count you cannot interchange the block with moveable memory in functions like DDE or the clipboard.
Posted on 2004-03-03 14:51:34 by donkey
I recall that some Win16 application code actually used this information, so the feature was retained for porting code. I don't remember which Win16 book detailed this information.
Posted on 2004-03-03 14:53:47 by tenkey
Ok, I guess there's no problem with using a GMEM_FIXED pointer in place of a 'handle' then - as long as you don't use a 'handle' as a memory pointer :)
Posted on 2004-03-03 14:58:15 by f0dder
Hi Tenkey,

Yeah, I think that in order to retain compatibility with Win16 the clipbaord and DDE was required to retain the moveable memory concept and as far as I can tell they are the only things left that rely on the handles as they must unlock the memory so they check that the reference count is 0 before proceding. Besides that I can't find another example that absolutely requires a 0 reference count.

PS nice that the board is running smoothly again :)
Posted on 2004-03-03 15:00:40 by donkey