Jump to content


Photo

Tiled GUI background?


  • Please log in to reply
6 replies to this topic

#1 ManaUser

ManaUser
  • Members
  • 1121 posts

Posted 23 December 2007 - 12:06 AM

Anyone know a convenient way to tile an image to fill a GUI? I would have thought there'd be an easy way to do this but I can't find it of so. I could always just use a bunch of picture controls, but if there's a command I've forgotten anyone knows as some DLL wizardry for this, I'd appreciate it.

#2 Guests

  • Guests

Posted 23 December 2007 - 11:38 AM

There is a GDI+ crop function somewhere on the forum

#3 dmatch

dmatch
  • Members
  • 252 posts

Posted 23 December 2007 - 05:57 PM

I could always just use a bunch of picture controls, but if there's a command I've forgotten anyone knows as some DLL wizardry for this, I'd appreciate it.

The bunch of pictures is really slow on my older system, but it does work:
Gui,Margin,0,0
Gui, +resize
Gui,add,picture,x0 y0 w100 h100 hwndhPic,c:\YourPicture.jpg.png.etc
Gui,Show,x0 y0 w%A_ScreenWidth% h%A_ScreenHeight%,Test
x:=0
y:=0
Loop
{
	x+=100
	if(x >= A_ScreenWidth){
		x:=0
		y+=100
		if(y >= A_ScreenHeight)
			break
	}
	Gui,Add,Picture,x%x% y%y% w100 h100,c:\YourPicture.jpg.png.etc
}
Gui,Show,x100 y100 w400 h400
return
GuiClose:
ExitApp
Here is a much faster way using......drum roll please......DllCalls to GDI.
w:=100 ;width of individual tile
h:=100 ;height of individual tile
Gui, +resize
Gui,add,picture,x0 y0 w%w% h%h% hwndhPic,c:\YourPicFileHere.jpg.png.etc
SendMessage,0x173,0,0,,ahk_id %hPic% ;0x173 is STM_GETIMAGE
hBMCopy:=ErrorLevel
;Get a copy of the picture
hBM:=DllCall("CopyImage",uint,hBMCopy,uint,0,int,0,int,0,uint,0x2000)
;Get device context for picture
hDC:=DllCall("GetDC",uint,hPic,uint)
;Create compatible device context to put picture in
hCDC:=DllCall("CreateCompatibleDC",uint,hDC,uint)
;Put the picture in the CDC 
DllCall("SelectObject",uint,hCDC,uint,hBM)
;Create compatible device context to hold tiled image
hCDC2:=DllCall("CreateCompatibleDC",uint,hDC,uint)
;Create an empty bitmap to trap the tiled image in
hBM2:=DllCall("CreateCompatibleBitmap",uint,hDC,int,A_ScreenWidth,int,A_ScreenHeight,uint)
;Put the empty image in so can draw on it
DllCall("SelectObject",uint,hCDC2,uint,hBM2)

x:=-1*w
y:=0
Loop
{
	x+=w
	if(x >= A_ScreenWidth){
		x:=0
		y+=h
		if(y >= A_ScreenHeight)
			break
	}
	;Build the tiled image in the compatible heretofore empty bitmap
	DllCall("BitBlt",uint,hCDC2,int,x,int,y,int,w,int,h,uint,hCDC,int,0,int,0,uint,0xcc0020)
}
;Cleanup
DllCall("ReleaseDC",uint,hPic,uint,hDC)
DllCall("DeleteObject",uint,hCDC)
DllCall("DeleteObject",uint,hCDC2)
DllCall("DeleteObject",uint,hBM)
;Apply the tiled image to the original picture
SendMessage,0x172,0,hBM2,, ahk_id %hPic% ;0x172 is STM_SETIMAGE message
if(ErrorLevel && hBM2 <> ErrorLevel)
	DllCall("DeleteObject",uint,errorlevel)
Gui, Show, x100 y100 w400 h400, Test
return
GuiClose:
ExitApp
This works on Windows Me. I think it should work on XP also. I have found some differences in the way XP handles static images as compared to Me. I believe it was XP that required me to start doing the CopyImage call.

Anyway give this a try and see if it works for you.

dmatch

#4 ManaUser

ManaUser
  • Members
  • 1121 posts

Posted 24 December 2007 - 07:17 AM

Yes, the DLL method works nicely. I wasn't expecting it would take quite that much code, but it does exactly what I wanted. Thanks! Extra thanks for the helpful commends, I am trying to gradually get a handle on how to use these external functions.

#5 dmatch

dmatch
  • Members
  • 252 posts

Posted 24 December 2007 - 04:56 PM

You're welcome.

I wasn't expecting it would take quite that much code


Actually, that's not too out of the ordinary for C programming with Windows API and that essentially is what the code is doing.

I am trying to gradually get a handle on how to use these external functions.


MSDN.com is a source for info on the Windows API or you can get the SDK helpfile (click here). You would also need a list of Windows constants (such as STM_SETIMAGE used in the code above). Those are in include/header (winuser.h, wingdi.h etc) files so you would either need them or access to these constants. SKAN has posted a useful tool for fetching constants here:
http://www.autohotke...topic19766.html
With the above mentioned stuff you could gradually get a handle on it. :wink:

Good Luck,

dmatch

#6 Kiera

Kiera
  • Guests

Posted 27 May 2010 - 10:21 PM

Dmatch, when I use your code to tile images, I'm running into a small problem.

If I add an image to the GUI before "Gui, Show", it comes up just fine.

But if I add an image afterwards (for example, as a result of pressing a button), it doesn't come up unless I either hit the button a second time, or unless I add "WinSet, Redraw" after the add image line - which causes undesirable flickering when I've got a more complicated GUI.

Is there any way to get it to show up properly the first time that doesn't cause flicker?


Here's some sample code:


TileImage(TpicOutputVar, TileWidth, TileHeight)
{
	
	Global
	
	;  Set the dimensions of each individual tile.
	w := TileWidth
	h := TileHeight
	
	SendMessage,0x173,0,0,,ahk_id %TpicOutputVar% ;0x173 is STM_GETIMAGE
	hBMCopy:=ErrorLevel
	
	;Get a copy of the picture
	hBM:=DllCall("CopyImage",uint,hBMCopy,uint,0,int,0,int,0,uint,0x2000)
	
	;Get device context for picture
	hDC:=DllCall("GetDC",uint,TpicOutputVar,uint)
	
	;Create compatible device context to put picture in
	hCDC:=DllCall("CreateCompatibleDC",uint,hDC,uint)
	
	;Put the picture in the CDC
	DllCall("SelectObject",uint,hCDC,uint,hBM)
	
	;Create compatible device context to hold tiled image
	hCDC2:=DllCall("CreateCompatibleDC",uint,hDC,uint)
	
	;Create an empty bitmap to trap the tiled image in
	hBM2:=DllCall("CreateCompatibleBitmap",uint,hDC,int,A_ScreenWidth,int,A_ScreenHeight,uint)
	
	;Put the empty image in so can draw on it
	DllCall("SelectObject",uint,hCDC2,uint,hBM2)
	
	x := -1 * w
	y := 0
	
	Loop
	{
		x += w
		if (x >= A_ScreenWidth)
		{
			x:=0
			y+=h
			if (y >= A_ScreenHeight)
			{
				break
			}
		}
		
		;Build the tiled image in the compatible heretofore empty bitmap
		DllCall("BitBlt",uint,hCDC2,int,x,int,y,int,w,int,h,uint,hCDC,int,0,int,0,uint,0xcc0020)
	}
	
	
	;  Cleanup
	DllCall("ReleaseDC",uint,TpicOutputVar,uint,hDC)
	DllCall("DeleteObject",uint,hCDC)
	DllCall("DeleteObject",uint,hCDC2)
	DllCall("DeleteObject",uint,hBM)
	
	;Apply the tiled image to the original picture
	SendMessage, 0x172, 0, hBM2,, ahk_id %TpicOutputVar%  ;0x172 is STM_SETIMAGE message
	
	if (ErrorLevel && hBM2 <> ErrorLevel)
	{
		DllCall("DeleteObject",uint,errorlevel)
	}
	

}



Gui, +Resize

Gui, 1:Add, Pic, x0 y0 w128 h128 hwndTiledPic, %A_WorkingDir%\Images\yukon.jpg
TileImage(TiledPic, 128, 128)

Gui, Add, Button,x10 y10, Show Images

;  This images comes up just fine.
Gui, 1:Add, Pic, x500 y500 BackgroundTrans AltSubmit, %A_WorkingDir%\Deck\RD2.png

Gui, Show, Maximize
Return 


ButtonShowImages:

	;  This image won't come up unless you hit the button a second time, or add "WinSet, Redraw" after this line.
	Gui, 1:Add, Pic, x100 y100 BackgroundTrans AltSubmit, %A_WorkingDir%\Deck\GD2.png
	

Return


GuiClose: 
ExitApp



#7 dmatch

dmatch
  • Members
  • 252 posts

Posted 28 May 2010 - 02:03 PM

I don't know what to tell you about the need for a second click to show the image (or winset redraw) except that it might be a Windows message timing issue that might be different from one system to another. The image appears on the first click on my old ME system without Winset, Redraw being used.

I also see a flash (flicker) when a picture is displayed the second and subsequent times but not the first time. I tried using GuiControl to change the picture instead of adding it each time but the flash is still there. I have run into this sort of thing many times when manipulating images in Autohotkey. I am not usually able to resolve that issue so can't be of help on that. Maybe someone else can suggest potential solutions.

dmatch