WinAPI help

Archives Forums/Win32 Discussion/WinAPI help

David Boudreau(Posted 2008) [#1]
I'm currently having trouble with a crash from these WinAPI lines of code:
hwnd = QueryObject (window_handle, 1)
api_SetWindowLong(hwnd, -20,  $80000)
api_SetLayeredWindowAttributes(hwnd, colorkey, alpha, colororalpha)
api_InvalidateRect(api_GetDesktopWindow(), Null, True)

This is in a .bb (BlitzPlus) program using decls files. The last line causes the crash and I'm not sure why it crashes or how to get it to work without crashing. Without the last line, the desktop doesn't get refreshed.


Kev(Posted 2008) [#2]
Hi David, Sorry its taken so long to get back to you.

Your using a canvas, is a canvas not a directx surface? try removing it from the window or make a small example using just the window.

left me know how you get on, ive just downloaded blitzplus as ive not used it in years. can i also look at the .decls your using where api_InvalidateRect() is defined.

kev


David Boudreau(Posted 2008) [#3]
Thanks Kev... when I remove the canvas (and cls/flipcanvas lines etc) it still crashes just as before (and, similarly, runs ok when I also remove the InvalidatRect line, same as before).

"is a canvas not a directx surface?" Good question! I do not know what exactly a canvas is. My best guess would be a hdc but I don't totally understand what that is either, other than general things I can with one using just BlitzPlus.

Here is the def in my user32.decls file:
.lib "user32.dll"
[...]
api_InvalidateRect% (hwnd%, lpRect*, bErase%) : "InvalidateRect"
[...]

Happy to post more or all of the code if you like.


Kev(Posted 2008) [#4]
Dave

change your decls def from
api_InvalidateRect% (hwnd%, lpRect*, bErase%) : "InvalidateRect"

to
api_InvalidateRect% (hwnd%, lpRect%, bErase%) : "InvalidateRect"


lpRect is being passed as a bank this is the reason for your crash, Your passing NULL and its expecting a bank.

kev


David Boudreau(Posted 2008) [#5]
I might as well post the entire .bb file:

win = CreateWindow("Test",0,0,600,400,Desktop(),0);
canvas = CreateCanvas(200,200,32,32,win); SMALL CANVAS 32x32
SetGadgetLayout canvas,1,1,1,1
SetBuffer CanvasBuffer(canvas)

skin_window(win,"test.bmp",canvas, $FFFFFF,100,3);
;^^^^^THIS CALLS THE RELEVANT FUNCTION^^^^^^

timer = CreateTimer (60)
Global timerframes
winsym = LoadImage("winsym.bmp") ; 24x24 bmp top-left pixel black

Repeat
  Select WaitEvent()
  Case $101
    Select EventData()
    
	Case 1
    	End
    End Select    
	
	Case $4001;   THIS SECTION JUST TO MAKE WIN DRAGABLE
    If MouseDown(1) Then	
     If gedrueckt = 0 Then		
       maus_X = MouseX()
       maus_Y = MouseY()
       fenster_X = GadgetX(win) 
       fenster_Y = GadgetY(win)
       gedrueckt = 1
     Else 
       neues_maus_X = MouseX()
       neues_maus_Y = MouseY()
       differenz_X = maus_X - neues_maus_X
       differenz_Y = maus_Y - neues_maus_Y
       fenster_X = fenster_X - differenz_X
       fenster_Y = fenster_Y - differenz_Y
       maus_X = neues_maus_X
       maus_Y = neues_maus_Y	
       SetGadgetShape (win, fenster_X, fenster_Y, 600,400)
     End If
    Else 
	    gedrueckt = 0
	  End If
	 End Select
	
	Select EventID()
    Case $803 ; Window Close
        End
	Case $4001 ; Timer tick
		Cls
		If JoyDown(1) Then
			DrawImage(winsym,0,0); x,y
		EndIf
		FlipCanvas(canvas)
	End Select; ends EventID() select	
Forever

Function skin_window(window_handle, image_path$,panel,colorkey,alpha,colororalpha)
;^^^HipTeen CALLED THAT ARG PANEL BUT IN MY CASE IT'S
;ACTUALLY A CANVAS... HERE IS HIS COMMENTS:
; colorkey is transparency color in hexadecimal form, black ist for example $FFFFFF
; alpha describes the opacity of the window, 0 for full translucent and 255 for non translucent
; use coloralpha to choose the mode you want to use
; 1 to set one color fully lucent
; 2 to set the level of the transperence of the whole window
; 3 to do both
; I think the rest ist self-explanatory
   
	;If Not panel Then
   ;  panel = CreatePanel (0,0,GadgetWidth (window_handle), GadgetHeight (window_handle), window_handle)
	;End If
   ;SetPanelImage canvas, image_path$ ; panel,

   hwnd = QueryObject (window_handle, 1); these 3 lines needed for transparency effect
   api_SetWindowLong(hwnd, -20,  $80000) ; -20 GWL(getwindowLong)_EXSTYLE
   api_SetLayeredWindowAttributes(hwnd, colorkey, alpha, colororalpha)
api_InvalidateRect(api_GetDesktopWindow(), Null, True) ;(GetDesktopWindow(), Null, True)
;api_RedrawWindow(api_GetDesktopWindow(),Null,hwnd,RDW_ERASE)
;api_SendMessage(api_GetDesktopWindow(), WM_PAINT, 0,0)
End Function



David Boudreau(Posted 2008) [#6]
Thanks Kev, I did as you mentioned, but got a message "Illegal type conversion".

In fact I think I tried that before, after reading a forum post saying something similar, but changed it back again when I got this error. When lprect% is an int%(?) instead of a bank(lprect*), you're saying it should work ok? It gives that error "Illegal type conversion".

If I change it back to the way I had it (as a bank, or lprect*), would I be able to make pass InvalidateRect the NULL argument in the format of a bank? (If that's possible with Blitz banks and WinAPI decls lines....)

(and as you likely know, MSDN says it's a * "If this parameter is NULL, the entire client area is added to the update region. " but maybe it can be changed as you describe somehow?)

Just in case this is relevant, my InvalidateRect passes another api as the first argument; this is defined as such in my .decls:

api_GetDesktopWindow% () : "GetDesktopWindow"


Kev(Posted 2008) [#7]
Dave pass 0 not NULL as lprect in the InvalidateRect() call.

kev


David Boudreau(Posted 2008) [#8]
Ah ok-- done, I now pass 0 instead of NULL. It does not crash, however, the canvas still leaves the junk shadows all under itself on an unrefreshed desktop. (Same behavior as before without the InvalidateRect() line.)


Kev(Posted 2008) [#9]
Hi Dave

This works here

decls
.lib "user32.dll"
api_SetWindowLong%(hwnd%,nIndex%,dwNewLong%):"SetWindowLongA" 
api_SetLayeredWindowAttributes%(hwnd%,crKey%,bAlpha%,dwFlags%):"SetLayeredWindowAttributes" 
api_InvalidateRect%(hwnd%,lpRect%,bErase%):"InvalidateRect"


and the example
win = CreateWindow("Test",0,0,600,400,Desktop(),0);
canvas = CreateCanvas(200,200,32,32,win); SMALL CANVAS 32x32
SetGadgetLayout canvas,1,1,1,1
SetBuffer CanvasBuffer(canvas)

skin_window(win,"test.bmp",canvas, $FFFFFF,100,3);
;^^^^^THIS CALLS THE RELEVANT FUNCTION^^^^^^

timer = CreateTimer (60)
Global timerframes
winsym = LoadImage("winsym.bmp") ; 24x24 bmp top-left pixel black

Repeat
  Select WaitEvent()
  Case $101
    Select EventData()
    
	Case 1
    	End
    End Select    
	
	Case $4001;   THIS SECTION JUST TO MAKE WIN DRAGABLE
    If MouseDown(1) Then	
     If gedrueckt = 0 Then		
       maus_X = MouseX()
       maus_Y = MouseY()
       fenster_X = GadgetX(win) 
       fenster_Y = GadgetY(win)
       gedrueckt = 1
     Else 
       neues_maus_X = MouseX()
       neues_maus_Y = MouseY()
       differenz_X = maus_X - neues_maus_X
       differenz_Y = maus_Y - neues_maus_Y
       fenster_X = fenster_X - differenz_X
       fenster_Y = fenster_Y - differenz_Y
       maus_X = neues_maus_X
       maus_Y = neues_maus_Y	
       SetGadgetShape (win, fenster_X, fenster_Y, 600,400)
     End If
    Else 
	    gedrueckt = 0
	  End If
	 End Select
	
	Select EventID()
    Case $803 ; Window Close
        End
	Case $4001 ; Timer tick
		Cls
		If JoyDown(1) Then
			DrawImage(winsym,0,0); x,y
		EndIf
		FlipCanvas(canvas)
	End Select; ends EventID() select	
Forever

Function skin_window(window_handle, image_path$,panel,colorkey,alpha,colororalpha)
;^^^HipTeen CALLED THAT ARG PANEL BUT IN MY CASE IT'S
;ACTUALLY A CANVAS... HERE IS HIS COMMENTS:
; colorkey is transparency color in hexadecimal form, black ist for example $FFFFFF
; alpha describes the opacity of the window, 0 for full translucent and 255 for non translucent
; use coloralpha to choose the mode you want to use
; 1 to set one color fully lucent
; 2 to set the level of the transperence of the whole window
; 3 to do both
; I think the rest ist self-explanatory
   
	;If Not panel Then
   ;  panel = CreatePanel (0,0,GadgetWidth (window_handle), GadgetHeight (window_handle), window_handle)
	;End If
   ;SetPanelImage canvas, image_path$ ; panel,

   hwnd = QueryObject (window_handle, 1); these 3 lines needed for transparency effect
   api_SetWindowLong(hwnd, -20,  $80000) ; -20 GWL(getwindowLong)_EXSTYLE
   api_SetLayeredWindowAttributes(hwnd, colorkey, alpha, colororalpha)
   ;api_InvalidateRect(api_GetDesktopWindow(), Null, True) ;(GetDesktopWindow(), Null, True)
;api_RedrawWindow(api_GetDesktopWindow(),Null,hwnd,RDW_ERASE)
;api_SendMessage(api_GetDesktopWindow(), WM_PAINT, 0,0)
End Function


the window moves clean and the desktop does not curupt, you could try api_InvalidateRect(QueryObject(Desktop(),1), 0, True)

kev


David Boudreau(Posted 2008) [#10]
Really? I copied and pasted your code into a new file, and it still corrupts my desktop. I also tried the
api_InvalidateRect(QueryObject(Desktop(),1), 0, True)

but got the same result. I am on Windows 2000.

I compiled two .exes, one with that InvalidateRect line, and one without, and tried it on an XP laptop but the same behavior happens, the desktop gets corrupted any place the canvas had been over, left unrefreshed after exiting program and canvas is not transparent (window is transparent as desired, just not the canvas, same as before).

On my Win2k machine here, video settings are 24 bit depth (High Color) 1024x768, if that matters. Did you happen to try this only on Vista?

And thanks again for all your help with this, I really appreciate it.


Kev(Posted 2008) [#11]
Dave yes i tested on my vista, i will try this later on xp and let you no the results

ive compiled the example here, test this version.
http://www.whitegatesoftware.com/test.zip

b.t.w are you using the latest update for blitzplus v1.45

kev


SebHoll(Posted 2008) [#12]
Dave yes i tested on my vista, i will try this later on xp and let you no the results

The reason why it works on Vista is because of Desktop Composition, which XP and the earlier Microsoft operating systems don't have. This problem was reported with MaxGUI so I simply ended up disabling SetGadgetAlpha() for windows with canvases. :(


David Boudreau(Posted 2008) [#13]
Kev- Thanks, I got your compiled exe and ran it on both XP and 2000 but still got the same problem as before. Yes, confirmed I'm running BlitzPlus V1.45 here (even downloaded it again to be sure- I guess we can't trust our Help-About dialog, as it still says 1.44 for each of the three IDE/linker/runtime). But please let me know if you got this working (without corrupted desktop) on XP. btw I tested this before but just to mention it, I don't think the code requires an actual test.bmp bitmap before running it, somehow, despite the fact that's what the function argument is (I don't quite understand why but with or without a test.bmp file, it doesn't seem to matter). I left it that way because in Hip Teen's original code, he did this with a panel and might have setpanelbackgrounded inside the function.

SebHoll- Thanks for mentioning that, but is that a definitive answer that what I am trying to do is impossible on windows 2000 and XP? Please tell me it ain't so! Even if the canvas won't be transparent, I can still work with that, as long as it doesn't crap all over my desktop and cause it to not even refresh itself. If not can you imagine any feasible workarounds to this? I searched Desktop Composition and saw your post here (what degac describes sounds exactly like my problem in that thread though I can't see his images).


John Blackledge(Posted 2008) [#14]
David,

Kev's exe works fine for me.

The grey area floats and allows sight of the desktop, the black square erases anything it passes over.
There is no 'border' left over when moving.

Pentium4 1.60 Ghz 768MB Ram, Nvidia GeForce4 Ti4200, DirectX 9

John


David Boudreau(Posted 2008) [#15]
John, what OS are you using? Reading your description of the behavior, the "black square" (which is the 32x32 canvas) "erases" anything it passes over (colors it black) but that's not what I'd call working fine! :) It corrupts the user's desktop and leaves canvas crap all over it (Win2k,XP) even after the user exits the program. Manually refreshing the desktop/bringing other windows into focus is the only way I have gotten rid of the corrupted area. I just wish my program wouldn't make the Desktop to forget to Cls and flip properly, so to speak. Even if I make the window unmoveable/undragable, it still leaves a very literal black mark (where the canvas was located over) after exiting.

Sorry I'm not sure what you mean by border left over when moving... The window style is 0 so that is why there is no border, (I think this style might be necessary for the SetLayeredWindowAttributes call) and the canvas leaves a filled black box....

In the original InvalidateRect() crash, though it crashed, the canvas was translucent (semi-transparent) along with its window on Win2k/XP.

If anyone has a decent workaround to fake it somehow e.g. get under the window without any strain on older PCs, I'm definitely interested (maybe better to make a new thread for that if it's confirmed this cannot work).


John Blackledge(Posted 2008) [#16]
Sorry I thought it was supposed to do that (-black square).

I thought the window border being left on the desktop was the original problem, which is not happening.

XP home SP 2.