News:

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

How to use GetLayeredWindowAttributes

Started by Squeeto, May 08, 2007, 10:06:28 PM

Previous topic - Next topic

Squeeto

Ok, I am a noobie but I have been looking for a few days now and I can't find a solution.
Time to post a question.

How do I code a GetLayeredWindowAttributes so that I can know the current values for opacity and color key?

I know that the following is wrong but it is the easiest way to show what I want.


.data
...
GetLWAsName db "GetLayeredWindowAttributes",0

...


GetTransparent proc hWnd:HANDLE
   LOCAL hLib:HANDLE
   LOCAL GetLWA:HANDLE
   LOCAL bAlpha:BYTE

   invoke LoadLibrary,addr User32lib
   mov hLib,eax
   .IF eax
      invoke GetProcAddress, hLib, addr GetLWAsName
      mov GetLWA, eax
      .IF eax
        call [GetLWA]   ;(hWnd,color,opacity,flags or hwnd,crKey,bAlpha,dwFlags)
        mov bAlpha, ah

        ;do something here
      .ENDIF
      invoke FreeLibrary,hLib
   .ENDIF
   ret
GetTransparent endp


The:
call [GetLWA]
mov bAlpha, ah
is wrong so how is this done?

Thank you

MichaelW

To successfully call the function using the address returned by GetProcAddress, your code must first push the function parameters onto the stack. The parameters must be pushed in right to left order (so you would push the rightmost parameter first). For the three parameters that start with *p, you must pass the address of the variable that will receive the value. To do this with stack (LOCAL) variables you must use LEA to get the address into a register, and then push the register.

MSDN: GetLayeredWindowAttributes

There is an additional problem:
QuoteGetLayeredWindowAttributes can be called only if the application has previously called SetLayeredWindowAttributes on the window.

If you search the forum for "translucent" you will find a translucent dialog demo that uses a layered window.

eschew obfuscation

Squeeto

Thanks for the quick response MichaelW.
QuoteTo successfully call the function using the address returned by GetProcAddress, your code must first push the function parameters onto the stack.

I know this is how it is done for SetLayeredWindowAttributes; I have already made this work.  It seems strange to push parameters that you want to retrieve.  I figured that you make a 'Get' call and pop the results.
I am beginning to think that this is not the function call I need?  Especially if "GetLayeredWindowAttributes can be called only if the application has previously called SetLayeredWindowAttributes".

Maybe I need something like:
invoke GetWindowLong,hWnd,GWL_EXSTYLE
but for opacity and color key.

The problem is I won't know how to do this until I have seen it done.

I will search the forum for “translucent” and see what shows.

Squeeto

I looked for a few hours to find this, still no luck.
Ok, here is my attempt:

.data
...
GetLWAsName db "GetLayeredWindowAttributes",0

...


GetTransparent proc hWnd:HANDLE
   LOCAL hLib:HANDLE
   LOCAL GetLWA:HANDLE
   LOCAL dwFlags:BYTE
   LOCAL bAlpha:BYTE

   invoke LoadLibrary,addr User32lib
   mov hLib,eax
   .IF eax
      invoke GetProcAddress, hLib, addr GetLWAsName
      mov GetLWA, eax
      .IF eax
        mov al, dwFlags  ;is bit 2 set (2h) to show that opacity is used?
        push eax
        mov al,bAlpha  ;% opacity (0-255)
        push eax
        push NULL     ;transparent color- I don't need this
        push hWnd
        call [GetLWA]   ;(hWnd,color,opacity,flags or hwnd,crKey,bAlpha,dwFlags)

        lea eax, dwFlags      ;Load Effective Address of the flags
        ;eax now holds 1h (for color key), 2h (for opacity), or 3h for both ??
        ;do something here
        lea eax, bAlpha    ;Load Effective Address of the opacity
        ;do something here
      .ENDIF
      invoke FreeLibrary,hLib
   .ENDIF
   ret
GetTransparent endp


This doesn't quite work.  LEA returns incorrect values.  Could you clean this up for me?

MichaelW

Under Win32 a pointer is a 32-bit value, regardless of what it points to.

.IF eax
  lea eax, dwFlags ; assembles to lea eax,[ebp-9]
  push eax
  lea eax, bAlpha  ; assembles to lea eax,[ebp-0Ah]
  push eax
  push NULL
  push hWnd
  call GetLWA
  or eax, eax
  jnz @F
  ; function failed, free library and return zero.
  invoke FreeLibrary,hLib
  xor eax, eax
  ret
@@:
  ; dwFlags now holds whatever the function put there
  ; bAlpha now holds whatever the function put there
.ENDIF

eschew obfuscation

Squeeto

I tried this and it failed at the jnz and returns early.

I better show you my exact code.  Maybe I made another error.
I set the taskbar transparent with a certain color key.  This is easy to do.  What I want is to leave the opacity setting if another program has already set it.  Thus the  GetLayeredWindowAttributes.


invoke FindWindow,addr Shell_TrayWndName,NULL ; get traybar\taskbar handle
mov hTaskbar, eax
.if eax != 0
  invoke SetTransparent,hTaskbar,0646464h         ;set transparent color to 64,64,64
.endif

...

SetTransparent proc hWnd:HANDLE, crKey:COLORREF
   LOCAL hLib:HANDLE
   LOCAL GetLayeredWindowAttr:HANDLE
   LOCAL SetLayeredWindowAttr:HANDLE
   LOCAL dwFlags:BYTE
   LOCAL bAlpha:BYTE

   invoke LoadLibrary,addr User32lib
   mov hLib,eax
   .IF eax
     invoke GetProcAddress, hLib, addr GetLayeredWindowAttributesName
     mov GetLayeredWindowAttr, eax
     .IF eax
       lea eax, dwFlags   ;Load Effective Address of the flags
       push eax           ;is bit 2 set (2h) to show that opacity is used?
       lea eax, bAlpha  ;% opacity (0-255)
       push eax
       push NULL     ;transparent color which I will set
       push hWnd
       call GetLayeredWindowAttr   ;(hWnd,color,opacity,flags or hwnd,crKey,bAlpha,dwFlags)
       or eax, eax
       jnz @F
         ; function failed, free library and return zero.
         invoke FreeLibrary,hLib
         xor eax, eax
         ret
       @@:

       invoke GetProcAddress, hLib, addr SetLayeredWindowAttributesName
       mov SetLayeredWindowAttr, eax
       .IF eax
         invoke GetWindowLong,hWnd,GWL_EXSTYLE
         or eax, WS_EX_LAYERED
         invoke SetWindowLong, hWnd, GWL_EXSTYLE, eax

         xor eax, eax      ;not sure yet if I need this. I'll know when I get past the jnz :)
         mov al,dwFlags     
         or al,1h   ;set bit 1 so a color key is used and OR it with the existing value
         push eax
         xor eax, eax        ;not sure yet if I need this
         mov al,bAlpha     ;opacity %
         push eax
         xor eax,eax
         mov eax,crKey
         push eax     ;this pushes the transparent color
         push hWnd
         call SetLayeredWindowAttr
       .ENDIF
     .ENDIF
     invoke FreeLibrary,hLib
   .ENDIF
   ret
SetTransparent endp


BTW, thanks again for the help

MichaelW

dwFlags is supposed to be a DWORD. Sorry, I failed to see the error until just now. If that does not correct the problem, then one possibility is that your app has not previously called SetLayeredWindowAttributes. That was why I pointed you at some working code that does call SetLayeredWindowAttributes.

eschew obfuscation

Squeeto

No good.  It still returns at the jnz.
My app doesn't previously call SetLayeredWindowAttributes on the taskbar of course; I just want to know if another app did so that when I do call SetLayeredWindowAttributes, it doesn't change the opacity part.
I am sorry to have wasted your time on this.  I am just very surprised that MS wouldn't have made a provision for this in GetLayeredWindowAttributes.

My app (freeware btw) does work fine without the GetLayeredWindowAttributes part, so I may just alter it to have the user enter a opacity number.

There still might be a way to peek at system values; I will look a while longer.

Ty for the assistance.

Squeeto

Quote
Also, you need to remember some important things, like: 1. Registers EBX, ESI, EDI are all preserved across the Win32 API calls, so you can keep the values there and afetr you call Win32 they are NOT destroyed - VERY useful feature! 2. You MUST follow the same convention (save and restore EBX, ESI, EDI) only when you write the callback functions for Win32, such as: dialog procedures, window procedures, enumeration procedures, hooks, etc. - all functions that you pass to Win32 as parameters - it all goes with the same convention. Here is an example of correct WNDPROC function:
; --- TASM32 code sample...
MyWndProc Proc StdCall hWnd:DWORD, uiMsg:DWORD, wp:DWORD, lp:DWORD
  Push ebx
  Push esi
  Push edi

  ; ... your whole code here

ExitWndProc:
  Pop edi
  Pop esi
  Pop ebx
  Ret
MyWndProc EndP

Maybe this is the magic bullet that I need?