Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Color Zoomer/Picker & Screen Magnifier


  • Please log in to reply
72 replies to this topic
Sean
  • Members
  • 2462 posts
  • Last active: Feb 07 2012 04:00 AM
  • Joined: 12 Feb 2007
Yet another color picker with a floating zooming window under the cursor.

DOWNLOAD ColorZoomer.ahk.

Paulo-nli
  • Guests
  • Last active:
  • Joined: --
Wow!!
Another great script...and an unusual one. :shock:
I will need to spend the rest of the day reading msdn pages to understand what this script is doing.

Sean
  • Members
  • 2462 posts
  • Last active: Feb 07 2012 04:00 AM
  • Joined: 12 Feb 2007

Wow!!
Another great script...and an unusual one. :shock:
I will need to spend the rest of the day reading msdn pages to understand what this script is doing.

Thanks. In fact, this is the one I'm the most proud of.
BTW, it may not work in Windows below XP in its current form.
I'm ready to update it for W2K if there is a report of no working in it (:I don't think it'll ever work in w9x).

tic
  • Guests
  • Last active:
  • Joined: --
I want to have an on screen magnifier that follows the mouse around and on a key press, such as ctrl and + will increase the magnification and - will decrease it. I have taken the relevant parts from your script:

#NoEnv
#SingleInstance, Force
SetWinDelay, 10

nZ := 4                     ; Zoom Factor
nR := 220//2//nZ * nZ - 1   ; Rectangle of the Zoomer

CoordMode, Mouse
CoordMode, Pixel

ToolTip, %A_Space%

WinGet, hWnd, ID, ahk_class tooltips_class32
WinSet, ExStyle, +0x08000000, ahk_id %hWnd%

hDC_SC := DllCall("GetDC", "Uint", 0)
hDC_TT := DllCall("GetDC", "Uint", hWnd)

Loop
{
   MouseGetPos, xmouse, ymouse
   DllCall("StretchBlt", "Uint", hDC_TT, "int", 0, "int", 0, "int", 2*nR, "int", 2*nR, "Uint", hDC_SC, "int", xmouse-nR//nZ, "int", ymouse-nR//nZ, "int", 2*nR//nZ, "int", 2*nR//nZ, "Uint", 0x00CC0020)
   WinMove, ahk_id %hWnd%,, xmouse-nR, ymouse-nR, 2*nR, 2*nR


GetKeyState, state, NumpadAdd
if state = D
       goto Exit 
}

DllCall("ReleaseDC", "Uint", 0, "Uint", hDC_SC)
DllCall("ReleaseDC", "Uint", hWnd, "Uint", hDC_TT)


Exit:
ExitApp

but i was wondering how i could get the cursor to act normally through the program. Somehow make it think the window is transparent, but actually have it still showing?

Any help would be much appreciated

Laszlo
  • Moderators
  • 4713 posts
  • Last active: Mar 31 2012 03:17 AM
  • Joined: 14 Feb 2005
Nice! Thanks for sharing it!

Is there something I can change, such that semi-transparent windows are also shown? It would be nice if I could re-open the magnifier without restarting the script. Is it safe? Also, when the color value is shown, Ctrl-C or something could copy it to the ClipBoard. Is it hard to add?

Sean
  • Members
  • 2462 posts
  • Last active: Feb 07 2012 04:00 AM
  • Joined: 12 Feb 2007

but i was wondering how i could get the cursor to act normally through the program. Somehow make it think the window is transparent, but actually have it still showing?


I'm not 100% sure what you meant. I just guess you want so-called trans-mouse. If so, replace the following line in the script

WinSet, ExStyle, +0x08000000, ahk_id %hWnd%
with

WinSet, ExStyle, +0x00000020, ahk_id %hWnd%


Sean
  • Members
  • 2462 posts
  • Last active: Feb 07 2012 04:00 AM
  • Joined: 12 Feb 2007

Is there something I can change, such that semi-transparent windows are also shown?

Not sure this is directed to me. Anyway, there is no (semi-)transparent windows around here. Would you be a little more specific about what you have in mind?

It would be nice if I could re-open the magnifier without restarting the script. Is it safe? Also, when the color value is shown, Ctrl-C or something could copy it to the ClipBoard. Is it hard to add?

Actually in my own script, I used the directive #SingleInstance Off, so as to be able to trigger multiple instances of the script. Would you like to trigger the zoomer multiple times from the single instance of the script?

And, adding Ctrl-C is straightforward, especially with single instance of the picker, I think.

Laszlo
  • Moderators
  • 4713 posts
  • Last active: Mar 31 2012 03:17 AM
  • Joined: 14 Feb 2005

Is there something I can change, such that semi-transparent windows are also shown?

Not sure this is directed to me. Anyway, there is no (semi-)transparent windows around here. Would you be a little more specific about what you have in mind?

I meant, if I have semi-transparent windows shown (even when they are opaque), the magnifier box does not show them, but the windows underneath. As if the topmost windows were fully transparent.

I used the directive #SingleInstance Off, so as to be able to trigger multiple instances of the script. Would you like to trigger the zoomer multiple times from the single instance of the script?

When I got the color values and close the bubble, the script does not terminate, but cannot be activated again. I have to manually close the script, and restart when I need it again, otherwise there will be many dormant instances open (making the tray full of AHK icons). I think it is quite common to read the color values of several pixels, which could be much easier with a resident script, (re)activated with a hotkey. The question was, is it safe not to exit the script, but re-open the zoomer window?

adding Ctrl-C is straightforward, especially with single instance of the picker, I think.

Would you consider adding it to the script?

Sean
  • Members
  • 2462 posts
  • Last active: Feb 07 2012 04:00 AM
  • Joined: 12 Feb 2007

I meant, if I have semi-transparent windows shown (even when they are opaque), the magnifier box does not show them, but the windows underneath. As if the topmost windows were fully transparent.

Ah, I see.

Transparent windows, more precisely Layered windows, are not part of the screen. They live in different layers, similar to the Mouse cursor which I believe lives in sort of the topmost layer.
As a matter of fact, this is the underlying reason to make this apparently impossible script become really possible. The zoomer window, i.e., AHK's tooltip window, is a layered window itself!

Although it's possible to capture these layered windows (:see my screen capture script <!-- m -->http://www.autohotke...topic18146.html<!-- m --> ), it's not feasible here to do it. Then, this zoomer window would start capturing itself, so effectively nothing would be captured.

When I got the color values and close the bubble, the script does not terminate, but cannot be activated again. I have to manually close the script, and restart when I need it again, otherwise there will be many dormant instances open (making the tray full of AHK icons). I think it is quite common to read the color values of several pixels, which could be much easier with a resident script, (re)activated with a hotkey. The question was, is it safe not to exit the script, but re-open the zoomer window?

adding Ctrl-C is straightforward, especially with single instance of the picker, I think.

Would you consider adding it to the script?


I'll have to go now. I'll answer these part later.

tic
  • Members
  • 1934 posts
  • Last active: Dec 21 2015 01:05 PM
  • Joined: 22 Apr 2007
This works very nicely. Thank you very much! It's working nicely, but shows a double box when resizing. I posted this on the Help Forum but I figure you're the person to come to for help.

#NoEnv
#SingleInstance, Force
SetWinDelay, 10

size = 1

startagain:

nZ := 3                                       ; Zoom Factor
nR := size*100                            ; Rectangle of the Zoomer

CoordMode, Mouse
CoordMode, Pixel

ToolTip, %A_Space%

WinGet, hWnd, ID, ahk_class tooltips_class32
WinSet, ExStyle, +0x00000020, ahk_id %hWnd%


hDC_SC := DllCall("GetDC", "Uint", 0)
hDC_TT := DllCall("GetDC", "Uint", hWnd)

Loop
{
   MouseGetPos, xmouse, ymouse
   DllCall("StretchBlt", "Uint", hDC_TT, "int", 0, "int", 0, "int", 2*nR, "int", 2*nR, "Uint", hDC_SC, "int", xmouse-nR//nZ, "int", ymouse-nR//nZ, "int", 2*nR//nZ, "int", 2*nR//nZ, "Uint", 0x00CC0020)  
 WinMove, ahk_id %hWnd%,, xmouse-nR, ymouse-nR, 2*nR, 2*nR
   
       GetKeystate, state, NumpadAdd
       if state = D
{
         size += 0.1
         goto startagain
}
       GetKeystate, state, NumpadSub
       if state = D
{
     if size >= 1
       {
         size -= 0.1
         goto startagain
       }

}
   WinSet, AlwaysOnTop, On, ahk_id %hWnd%
}

F6::
Exit:
ExitApp

Controls are F6 to exit and numpad plus and minus to make larger and smaller. As you can see it flickers and a double box appears when resizing and I can't understand why (not that I understand what the whole of that stretchblt call does :D )

Thanks very much for making such a great script!

Sean
  • Members
  • 2462 posts
  • Last active: Feb 07 2012 04:00 AM
  • Joined: 12 Feb 2007

As you can see it flickers and a double box appears when resizing

It's because you created a new tooltip each time when resizing. You may prefer using it this way:

#NoEnv
#SingleInstance, Force
SetWinDelay, 10

nZ := 3				; Zoom Factor
nR := 100			; Rectangle of the Zoomer

CoordMode, Mouse
CoordMode, Pixel

ToolTip, %A_Space%

WinGet, hWnd, ID, ahk_class tooltips_class32
WinSet, ExStyle, +0x00000020, ahk_id %hWnd%

hDC_SC := DllCall("GetDC", "Uint",    0)
hDC_TT := DllCall("GetDC", "Uint", hWnd)

Loop
{
	If GetKeyState("NumpadAdd")
	   nR++
	If GetKeyState("NumpadSub") && nR > 100
	   nR--

	MouseGetPos, xmouse, ymouse
	DllCall("StretchBlt", "Uint", hDC_TT, "int", 0, "int", 0, "int", nR*2, "int", nR*2, "Uint", hDC_SC, "int", xmouse-nR//nZ, "int", ymouse-nR//nZ, "int", nR//nZ*2, "int", nR//nZ*2, "Uint", 0x00CC0020) 
	WinMove, ahk_id %hWnd%,, xmouse-nR, ymouse-nR, nR*2, nR*2
	WinSet, AlwaysOnTop, On, ahk_id %hWnd%
}

F6::
Exit:
DllCall("ReleaseDC", "Uint",    0, "Uint", hDC_SC)
DllCall("ReleaseDC", "Uint", hWnd, "Uint", hDC_TT)
ExitApp

Thanks very much for making such a great script!

Thanks!

Sean
  • Members
  • 2462 posts
  • Last active: Feb 07 2012 04:00 AM
  • Joined: 12 Feb 2007
Yet another, my own magnifier.
It'll also capture transparent windows, and mouse cursor too.

/*
Esc key: Exit the application.
*/
#NoEnv
#SingleInstance, Force
SetWinDelay, 10
CoordMode, Mouse

nZ := 3					                ; Zoom Factor
nW := A_ScreenWidth // 2 //2//nZ		; Width  of (small) Target Rectangle
nH := A_ScreenHeight// 6 //2//nZ		; Height of (small) Target Rectangle

ToolTip, %A_Space%
WinClose, ahk_class SysShadow
WinGet, hWnd, ID, ahk_class tooltips_class32

hDC_SC := DllCall("GetDC", "Uint",    0)
hDC_LW := DllCall("GetDC", "Uint", hWnd)
hDC_TT := DllCall("GetDC", "Uint", hWnd)

DllCall("SetStretchBltMode", "Uint", hDC_TT, "int", 4)

Loop
{
	MouseGetPos, xmouse, ymouse
	DllCall("BitBlt", "Uint", hDC_LW, "int", 0, "int", 0, "int", 2*nW, "int", 2*nH, "Uint", hDC_SC, "int", xmouse-nW, "int", ymouse-nH, "Uint", 0x40CC0020)
;	CaptureCursor(hDC_LW, nW, nH)		; Capture magnified mouse cursor too.
	DllCall("StretchBlt", "Uint", hDC_TT, "int", 0, "int", 0, "int", 2*nW*nZ, "int", 2*nH*nZ, "Uint", hDC_LW, "int", 0, "int", 0, "int", 2*nW, "int", 2*nH, "Uint", 0x00CC0020)
	CaptureCursor(hDC_TT, nW*nZ, nH*nZ)	; Capture un-magnified mouse cursor too.
	WinMove, ahk_id %hWnd%,, xmouse-nW*nZ-1, ymouse+nH, 2*nW*nZ+2, 2*nH*nZ+2

	If GetKeyState("Esc")
	   Break
}

DllCall("ReleaseDC", "Uint",    0, "Uint", hDC_SC)
DllCall("ReleaseDC", "Uint", hWnd, "Uint", hDC_LW)
DllCall("ReleaseDC", "Uint", hWnd, "Uint", hDC_TT)


CaptureCursor(hDC, xCenter, yCenter)
{
	VarSetCapacity(mi, 20, 0)
	mi := Chr(20)
	DllCall("GetCursorInfo", "Uint", &mi)

	ptr := &mi + 4
	bShow   := *ptr++ | *ptr++ << 8 | *ptr++ << 16 | *ptr++ << 24
	hCursor := *ptr++ | *ptr++ << 8 | *ptr++ << 16 | *ptr++ << 24

	DllCall("GetIconInfo", "Uint", hCursor, "Uint", &mi)

	ptr := &mi + 4
	xHotspot := *ptr++ | *ptr++ << 8 | *ptr++ << 16 | *ptr++ << 24
	yHotspot := *ptr++ | *ptr++ << 8 | *ptr++ << 16 | *ptr++ << 24
	hBMMask  := *ptr++ | *ptr++ << 8 | *ptr++ << 16 | *ptr++ << 24
	hBMColor := *ptr++ | *ptr++ << 8 | *ptr++ << 16 | *ptr++ << 24

	If hBMMask
	   DllCall("DeleteObject", "Uint", hBMMask)
	If hBMColor
	   DllCall("DeleteObject", "Uint", hBMColor)
	If bShow
	   DllCall("DrawIcon", "Uint", hDC, "int", xCenter - xHotspot, "int", yCenter - yHotspot, "Uint", hCursor)
}


Sean
  • Members
  • 2462 posts
  • Last active: Feb 07 2012 04:00 AM
  • Joined: 12 Feb 2007

When I got the color values and close the bubble, the script does not terminate, but cannot be activated again. I have to manually close the script, and restart when I need it again, otherwise there will be many dormant instances open (making the tray full of AHK icons). I think it is quite common to read the color values of several pixels, which could be much easier with a resident script, (re)activated with a hotkey. The question was, is it safe not to exit the script, but re-open the zoomer window?

I guess you closed them using other means than the defined hotkeys.
I think it's easy to correct using SetTimer which will check the visibility/existence of the zoomer window.
It's too bad to not be able to utilize the x button in the balloon tip.
It seems due to the persistent nature of the script when there exists non-trivial tooltip window created by AHK itself.

Would you consider adding it to the script?

Sure. BTW, how do you prefer it to behave? Automatic copy to the clipboard when picking the color?
Or, doing it when necessary via hotkey?
I found it rather non-trivial to use (the same) hotkey when multiple balloon tips are around.
And, in which format? RBG, BGR, or 0xBBGGRR (#...)...

tic
  • Members
  • 1934 posts
  • Last active: Dec 21 2015 01:05 PM
  • Joined: 22 Apr 2007
I dont understand why you never released that. It's the best magnifier I've seen on these forums. I've had a look at holomind and ivanw, and you managed to whip it up in no time.

I'm afraid you've gone too far above my understanding of ahk and the windows calls you use. I cant edit it! :0

I dont wanna use up your time with doing this, but my ambition is to make lots of things for a remote that will make it easier to use with windows. My project is with the wiimote and can be viewed here:
<!-- m -->http://www.wiili.org... ... t1528.html<!-- m -->

For my next release I had the idea of using the IR of the wiimote to allow you to point at the screen and at any time be able to zoom. I dont want the actual zoom to increase on a button press as I think 3 or 4 zoom is sufficient, but wanted the bounding area of the zoom to increase and decrease, and look like this pic from paper mario :D
<!-- m -->http://uk.media.wii.... ... 80431.html<!-- m -->

I managed to form an elipse over the magnifier you created, but the edges were jagged and was wondering if theres any way to antialiase them??
Also, is it possible to create a similar effect to paper mario on the rest of the screen where everything is slightly blurred and greyed out, and the mouse cursor needs to be within the zoom box.

Dont worry if thats a tall order, as I know it is!!! That last magnifier you just posted is so good! any more help would make my day

Laszlo
  • Moderators
  • 4713 posts
  • Last active: Mar 31 2012 03:17 AM
  • Joined: 14 Feb 2005
I would use the color picker script the following way:
- I start the script when needed normally, as other programs
- It stays resident, but does nothing
- Upon a hotkey press (Alt-Win-Z), the zoomer window pops up and follows the mouse
- At a mouse click the balloon tip comes up with the color value
- Esc closes it, until the next Alt-Win-Z
- Ctrl-C copies the color value to the clipboard, otherwise the same as Esc.
- A configuration window could be opened with Ctrl-Win-Alt-Z (which also closes the zoomer). Here you could set the color format, saved in an ini file, or in the registry.

The hotkeys are just examples, choose what you see fit.

I did not see a need for multiple instances of the script, except for comparing colors. If there is always at most one is open, a hotkey could copy the color value to the clipboard, without conflicts. For comparing colors, one could save the last 2 or 3 picked colors, and rotate the values in the current balloon tip upon a hotkey press (Alt-Win-Z).

These are just ideas. They may not work well in practice, but the script is very useful, so making it easier to use looks important.