Cool Excel Magnifying Glass to Zoom the entire Screen !

Jaafar Tribak

Well-known Member
Joined
Dec 5, 2002
Messages
9,858
Office Version
  1. 2016
Platform
  1. Windows
Hi all,

Here is a Magnifying Glass that you can use in Excel :) I am not sure about the usefulness of it in the normal day to day use of Excel but it's cool and was challenging to programme. The actual round Glass is actually a simple XL userorm whose standard styles were changed.

Here is a workbook example : https://www.box.com/shared/c1ujurjhkt

Just point to the round Glass with the mouse and move it around the screen to zoom in. It worked on my machine quite smoothly.

Here is the code that goes in a userform :

Code:
Option Explicit

Private Declare Function StretchBlt Lib "gdi32" _
(ByVal hdc As Long, ByVal X As Long, ByVal Y As Long, _
ByVal nWidth As Long, ByVal nHeight As Long, _
ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, _
ByVal nSrcWidth As Long, ByVal nSrcHeight As Long, ByVal dwRop As Long) As Long

Private Declare Function BitBlt Lib "gdi32" _
(ByVal hDestDC As Long, ByVal X As Long, ByVal Y As Long, _
ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, _
ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long

Private Const SRCCOPY = &HCC0020

Private Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hdc As Long) As Long

Private Declare Function CreateCompatibleBitmap Lib "gdi32" _
(ByVal hdc As Long, ByVal nWidth As Long, ByVal nHeight As Long) As Long

Private Declare Function SelectObject Lib "gdi32" _
(ByVal hdc As Long, ByVal hObject As Long) As Long

Private Declare Function DeleteObject Lib "gdi32" _
(ByVal hObject As Long) As Long

Private Declare Function OleCreatePictureIndirect Lib "olepro32.dll" _
(PicDesc As uPicDesc, RefIID As GUID, _
ByVal fPictureOwnsHandle As Long, IPic As IPicture) As Long

Private Declare Function DeleteDC Lib "gdi32" (ByVal hdc As Long) As Long

Private Declare Function GetDC Lib "user32" (ByVal hWnd As Long) As Long

Private lfrmDC As Long

Private Declare Function GetSystemMetrics Lib "user32" _
(ByVal nIndex As Long) As Long

Private Const SM_CXSCREEN = 0
Private Const SM_CYSCREEN = 1

Private Type GUID
    Data1 As Long
    Data2 As Integer
    Data3 As Integer
    Data4(7) As Byte
End Type
Private Type PicBmp
    Size As Long
    Type As Long
    hBmp As Long
    hPal As Long
    Reserved As Long
End Type
Private Type uPicDesc
    Size As Long
    Type As Long
    hPic As Long
    hPal As Long
End Type
Private Type RECT
    Left As Long
    Top As Long
    Right As Long
    Bottom As Long
End Type
Private Type POINTAPI
    Width As Long
    Height As Long
End Type
'________________________________________________________________________
Private Declare Function CreateEllipticRgn Lib "gdi32" _
                          (ByVal X1 As Long, ByVal Y1 As Long, _
                           ByVal X2 As Long, ByVal Y2 As Long) As Long

 Private Declare Function SetWindowRgn Lib "user32" _
                          (ByVal hWnd As Long, ByVal hRgn As Long, _
                           ByVal bRedraw As Long) As Long
'_________________________________________________________________________
Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" _
(ByVal hWnd As Long, ByVal nIndex As Long) As Long


Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" _
(ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long

Const GWL_STYLE = (-16)
Const WS_SYSMENU = &H80000
Private Const WS_CAPTION As Long = &HC00000

Private Declare Function DrawMenuBar Lib "user32" _
(ByVal hWnd As Long) As Long
'_________________________________________________________________________

Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
(ByVal lpClassName As String, ByVal lpWindowName As String) As Long

Private lfrmHwnd As Long

'_________________________________________________________________________


Private Declare Function SendMessage Lib "user32" _
Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, _
ByVal wParam As Long, lParam As Any) As Long

Private Declare Sub ReleaseCapture Lib "user32" ()

Private Const WM_NCLBUTTONDOWN = &HA1
Private Const HTCAPTION = 2

Private objCmb As CommandBar



Private Sub UserForm_Initialize()
    Dim lBmp As Long
    Dim IPic As IPicture
    Dim Screen As POINTAPI
    
    'assign the form handle to a module level var
    'will be needed throughout the module
    lfrmHwnd = FindWindow(vbNullString, Me.Caption)
    
    'setup the shape of our form so it looks
    'like a round magnifying glass
    Call FormSetUp(lfrmHwnd)
    
    'get the form dc on which the drawing will be made
    lfrmDC = GetDC(lfrmHwnd)
    
    'get the screen dimensions
    Screen = GetScreenDims
    
    'get a pointer of the screen bitmap
    lBmp = GetScrnBmpHandle(GetDC(0), 0, 0, Screen.Width, Screen.Height)
    
    'create a picture from the bitmap pointer
    Set IPic = GetBitmapPic(lBmp)
    
    'save bitmap to disk
    stdole.SavePicture IPic, (Environ("Temp")) & "\Scr.Bmp"
    'set the form picture to display the bitmap
     Me.Picture = LoadPicture((Environ("Temp")) & "\Scr.Bmp")
    
    'clean up
    Kill (Environ("Temp")) & "\Scr.Bmp"

End Sub


Private Sub UserForm_Activate()

    'the layout event doesn't fire here so refresh form now
    Me.Repaint
   Call UserForm_Layout
   
End Sub


Private Sub UserForm_Layout()

'update the userform background upon moving it
    StretchBlt _
     lfrmDC, 0, 0, Me.Width * 1.5, Me.Height * 1.5, _
     lMemoryDC, Me.Left * 1.5, Me.Top * 1.5, _
     Me.Width, Me.Height, SRCCOPY

End Sub

Private Sub UserForm_MouseDown _
(ByVal Button As Integer, ByVal Shift As Integer, _
ByVal X As Single, ByVal Y As Single)

    'show close menu
    If Button = 2 Then objCmb.ShowPopup

End Sub

Private Sub UserForm_MouseMove _
(ByVal Button As Integer, ByVal Shift As Integer, _
ByVal X As Single, ByVal Y As Single)

    'move the captionless form with the mouse
     If Button = 1 Then
        Call ReleaseCapture
        SendMessage lfrmHwnd, WM_NCLBUTTONDOWN, HTCAPTION, 0
    End If

End Sub

Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)

    'safety cleanup
    On Error Resume Next
    DeleteDC lMemoryDC
    CommandBars("GlassPopUp").Delete

End Sub

'****** Supporting functions **********************************


Private Function GetScrnBmpHandle _
(lScrDC As Long, lScrnLeft As Long, lScrnTop As Long, _
lScrnWidth As Long, lScrnHeight As Long) As Long

    Dim lBmp, lOldBmp As Long
    
    'create a temp memory dc on which to copy the current screen shot
    lMemoryDC = CreateCompatibleDC(lScrDC)
    
    'create a bmp
    lBmp = CreateCompatibleBitmap(lScrDC, lScrnWidth, lScrnHeight)
    
    'select the bmp onto the temp dc
    lOldBmp = SelectObject(lMemoryDC, lBmp)
    DeleteObject lBmp
    
    'copy the screen image onto the temp dc
    BitBlt lMemoryDC, 0, 0, lScrnWidth, lScrnHeight, _
    lScrDC, lScrnLeft, lScrnTop, SRCCOPY
    
    'return our bmp pointer
    GetScrnBmpHandle = lBmp

End Function

Private Function GetBitmapPic(ByVal lBmpHandle As Long) As IPicture

Dim r As Long, IPic As IPicture, IID_IDispatch As GUID, Pic As uPicDesc

    'Fill GUID info
    With IID_IDispatch
        .Data1 = &H20400
        .Data4(0) = &HC0
        .Data4(7) = &H46
    End With
    
    'Fill picture info
    With Pic
        .Size = Len(Pic) ' Length of structure
        .Type = 1  ' Type of Picture (bitmap)
        .hPic = lBmpHandle ' Handle to bitmap
        .hPal = 0 ' Handle to palette (may be null)
    End With
    'create the pic
    OleCreatePictureIndirect Pic, IID_IDispatch, 1, IPic
    Set GetBitmapPic = IPic


End Function


Private Function GetScreenDims() As POINTAPI

    'get screen width an height
    Dim r As POINTAPI
    
    With r
        .Width = GetSystemMetrics(SM_CXSCREEN)
        .Height = GetSystemMetrics(SM_CYSCREEN)
    End With
    GetScreenDims = r

End Function


Private Sub FormSetUp(lhwnd As Long)

    Dim lHr, IStyle As Long
    
    'adjust form dims
    Me.Width = 210
    Me.Height = 195
    
    'Create rightclick close menu
    On Error Resume Next
    CommandBars("GlassPopUp").Delete
    Set objCmb = Application.CommandBars.Add(Position:=msoBarPopup)
    With objCmb
        objCmb.Name = "GlassPopUp"
        With .Controls.Add(msoControlButton)
            .Caption = "CloseMe"
            .OnAction = "CloseGlass"
        End With
    End With
    On Error GoTo 0
    'set the mouse pointer so it simulates
    'that of a magnifying glass
    
    Me.MousePointer = fmMousePointerCross
    'make the userform captionless and round
    'so it simulates a magnifying glass
    
    IStyle = GetWindowLong(lhwnd, GWL_STYLE)
    IStyle = IStyle And Not WS_CAPTION 'And WS_THICKFRAME
    SetWindowLong lhwnd, GWL_STYLE, IStyle
    DrawMenuBar lhwnd
    lHr = CreateEllipticRgn(0, 0, Me.Width, Me.Height)
    SetWindowRgn lhwnd, lHr, True

End Sub


Copy the code below in a Standard Module :

Code:
Option Explicit

Public lMemoryDC As Long

Private Declare Function DeleteDC Lib "gdi32" (ByVal hdc As Long) As Long

Sub CloseGlass()

    On Error Resume Next
    DeleteDC lMemoryDC
    CommandBars("GlassPopUp").Delete
    Unload UserForm1

End Sub

Sub Bouton1_QuandClic()

    UserForm1.Show

End Sub

One nice touch that i haven't been able to give the magnifying glass is a frame around it so it can be more visible on the screen. Because of the round shape, framing the userform is quite difficult.

I have tested this on XL2003 Win XP French Version. I am hoping it also works for other XL versions.

Regards.
 
Last edited by a moderator:
Dear Jaafar,

Your code is great, thanks for that. I know it's an old post but I'd like to use your code with a rectangle shape instead of circle. Is it possible?
Thank you and have a great day.
 
Upvote 0
For rectangular type of Magnifying Glass do changes in Jaafar's code as follows:
1. In BasCaller module use this modification of the Test subroutine:
Rich (BB code):
Sub Test()
 
  Set Magnifier = New frmMagnifier
 
  ' use the  IntelliSense feature of the VBE.
  ' As you key in the letters,all the members of
  ' the Implement Class "ImpMagnifier" show up
  With Magnifier
    .FrameColor = vbGreen
    .FrameWidth = 3
    .FrameStyle = dot
    .Height = 150
    .Width = 150
    .MousePointer = fmMousePointerCross
    .ZoomFactor = 1.5
    '.Shape = elliptic
    .Shape = Rectangular
    .ShowMe
  End With
 
End Sub
2. In the code of frmMagnifier userform use this version of the UserForm_Layout subroutine:
Rich (BB code):
Private Sub UserForm_Layout()
 
  Dim lhr As Long
 
  ' set up defaults
  If P_ZoomFactor = 0 Then P_ZoomFactor = 1.5
 
  'update the userform background upon moving it
  StretchBlt _
      lfrmDC, 0, 0, Me.Width * P_ZoomFactor * 1.1, Me.Height * P_ZoomFactor * 1.1, _
      lMemoryDC, Me.Left * P_ZoomFactor, Me.Top * P_ZoomFactor, _
      Me.Width, Me.Height, SRCCOPY
 
  GetClientRect lfrmHwnd, tRect
 
  'define the form shapes now
  With tRect
    If P_MagShape = elliptic Then
      lhr = CreateEllipticRgn(0, 0, .Right - .Left, .Bottom - .Top)
      SetWindowRgn lfrmHwnd, lhr, True
      Arc lfrmDC, .Left, .Top, .Right - .Left - 5, .Bottom - .Top - 5, _
        .Right - .Left, .Right - .Left, .Bottom - .Top, .Bottom - .Top
    Else
      DrawEdge lfrmDC, tRect, EDGE_ETCHED, BF_RECT
    End If
  End With
 
End Sub
 
Last edited:
Upvote 0
Dear ZVI,

Thank you very-very much, you're awesome!

Ivan mentioned earlier in this post he has a version:
I did my one diff .... it actually gets an image area under the cursor and
displays it to the form, that way you get the image even when scrolling.
I know he shared his file but link doesn't work anymore:
xcelfiles.com
I also sent PM to him but no response.
Do you (or anyone else) has this version maybe?
Thank you and have a great day.

Kind Regards,

KeepTrying
 
Last edited:
Upvote 0
Ivan mentioned earlier in this post he has a version:

I know he shared his file but link doesn't work anymore:
xcelfiles.com
I also sent PM to him but no response.
Do you (or anyone else) has this version maybe?
Have found in my archive that Magnifier_XL.zip of Ivan F Moala, here is the link to its copy - Magnifier_XL.zip
 
Last edited:
Upvote 0
Dear Vladimir,

I cannot find words how grateful I am. Thanks a lot for Ivan, Jaafar and of course You to create/improve/share this fantastic work. You're all really altruistic and helpful.

Have a great day.

Regards,

KeepTrying
 
Last edited:
Upvote 0
Thank you for the feedback KeepTrying. All credits goes to Jaafar and Ivan as authors of their great code!
 
Last edited:
Upvote 0
Hi all,

I have a copy of Jaafar's original magnifying glass and it's one of the most magical things I've ever seen done in VBA. I need to be able to use it in a 64bit version of Excel. Does anyone know how to modify the code for this?
 
Upvote 0
Hi all,

I have a copy of Jaafar's original magnifying glass and it's one of the most magical things I've ever seen done in VBA. I need to be able to use it in a 64bit version of Excel. Does anyone know how to modify the code for this?

Hi Giordano,

Here is a new update of this old code... It uses a different code from the original.. it is cleaner and easier to use.

With this new code, the magnifier is now modeless so you can always work with excel while it is on display ..Also, the magnifier now should cover the whole screen not just excel and it updates automatically.

In order to close the magnifier, I have added a small x (close button) to its top corner ... You can also close it with ALT+F4.

And of course, the code should work with both 32 and 64 bit.

Download demo workbook

1- Add a new Class Module and give it the name of IMagnifier and put the following code in it:
Code:
Option Explicit

Public Sub Show( _
    ByVal Width As Long, _
    ByVal Height As Long, _
    ByVal ZoomFactor As Single, _
    Optional ByVal FrameColor As Long _
)

End Sub

2- Add a new userform , change its default name to ImpMagnifier and put the following code in its module:
Code:
Option Explicit

Implements IMagnifier

Private WithEvents cmbrs As CommandBars

Private Type POINTAPI
    X As Long
    Y As Long
End Type

Private Type RECT
    Left As Long
    Top As Long
    Right As Long
    Bottom As Long
End Type

[URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=If"]#If[/URL]  VBA7 Then
    [URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=If"]#If[/URL]  Win64 Then
        Private Declare PtrSafe Function GetWindowLong Lib "user32" Alias "GetWindowLongPtrA" (ByVal hwnd As LongPtr, ByVal nIndex As Long) As LongPtr
        Private Declare PtrSafe Function SetWindowLong Lib "user32" Alias "SetWindowLongPtrA" (ByVal hwnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As LongPtr) As LongPtr
        Private Declare PtrSafe Function PtInRect Lib "user32" (lpRect As RECT, ByVal arg2 As LongPtr) As Long
    [URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=Else"]#Else[/URL] 
        Private Declare PtrSafe Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As LongPtr, ByVal nIndex As Long) As LongPtr
        Private Declare PtrSafe Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As Long) As LongPtr
        Private Declare PtrSafe Function PtInRect Lib "user32" (lpRect As RECT, ByVal X As Long, ByVal Y As Long) As Long
    [URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=End"]#End[/URL]  If
    Private Declare PtrSafe Function WindowFromAccessibleObject Lib "oleacc" (ByVal pacc As IAccessible, phwnd As LongPtr) As Long
    Private Declare PtrSafe Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As LongPtr, ByVal hwnd As LongPtr, ByVal Msg As Long, ByVal wParam As LongPtr, ByVal lParam As LongPtr) As LongPtr
    Private Declare PtrSafe Function DrawMenuBar Lib "user32.dll" (ByVal hwnd As LongPtr) As Long
    Private Declare PtrSafe Function SetWindowPos Lib "user32" (ByVal hwnd As LongPtr, ByVal hWndInsertAfter As LongPtr, ByVal X As Long, ByVal Y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
    Private Declare PtrSafe Function SendMessage Lib "user32.dll" Alias "SendMessageA" (ByVal hwnd As LongPtr, ByVal wMsg As Long, ByVal wParam As LongPtr, ByRef lParam As Any) As Long
    Private Declare PtrSafe Function GetDC Lib "user32" (ByVal hwnd As LongPtr) As LongPtr
    Private Declare PtrSafe Function GetDeviceCaps Lib "gdi32" (ByVal hDC As LongPtr, ByVal nIndex As Long) As Long
    Private Declare PtrSafe Function ReleaseDC Lib "user32" (ByVal hwnd As LongPtr, ByVal hDC As LongPtr) As Long
    Private Declare PtrSafe Function CreateSolidBrush Lib "gdi32" (ByVal crColor As Long) As LongPtr
    Private Declare PtrSafe Function FrameRect Lib "user32" (ByVal hDC As LongPtr, lpRect As RECT, ByVal hBrush As LongPtr) As Long
    Private Declare PtrSafe Function DeleteObject Lib "gdi32" (ByVal hObject As LongPtr) As Long
    Private Declare PtrSafe Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
    Private Declare PtrSafe Function GetWindowRect Lib "user32" (ByVal hwnd As LongPtr, lpRect As RECT) As Long
    Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As LongPtr)
    Private Declare PtrSafe Function ReleaseCapture Lib "user32" () As Long
    Private Declare PtrSafe Function GetClientRect Lib "user32" (ByVal hwnd As LongPtr, lpRect As RECT) As Long
    Private Declare PtrSafe Function GetShellWindow Lib "user32" () As LongPtr
    Private Declare PtrSafe Function GetWindowDC Lib "user32" (ByVal hwnd As LongPtr) As LongPtr
    Private Declare PtrSafe Function BitBlt Lib "gdi32" (ByVal hDestDC As LongPtr, ByVal X As Long, ByVal Y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As LongPtr, ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long
    Private Declare PtrSafe Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As LongPtr
    Private Declare PtrSafe Function ClientToScreen Lib "user32" (ByVal hwnd As LongPtr, lpPoint As POINTAPI) As Long
    Private Declare PtrSafe Function IsWindowVisible Lib "user32" (ByVal hwnd As LongPtr) As Long
    Private Declare PtrSafe Function IsIconic Lib "user32" (ByVal hwnd As LongPtr) As Long
    Private Declare PtrSafe Function GetProcAddress Lib "kernel32" (ByVal hModule As LongPtr, ByVal lpProcName As String) As LongPtr
    Private Declare PtrSafe Function GetNextWindow Lib "user32" Alias "GetWindow" (ByVal hwnd As LongPtr, ByVal wFlag As Long) As LongPtr
    Private Declare PtrSafe Function FreeLibrary Lib "kernel32" (ByVal hLibModule As LongPtr) As Long
    Private Declare PtrSafe Function StretchBlt Lib "gdi32" (ByVal hDC As LongPtr, ByVal X As Long, ByVal Y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As LongPtr, ByVal xSrc As Long, ByVal ySrc As Long, ByVal nSrcWidth As Long, ByVal nSrcHeight As Long, ByVal dwRop As Long) As Long
    Private Declare PtrSafe Function CreateCompatibleDC Lib "gdi32" (ByVal hDC As LongPtr) As LongPtr
    Private Declare PtrSafe Function CreateCompatibleBitmap Lib "gdi32" (ByVal hDC As LongPtr, ByVal nWidth As Long, ByVal nHeight As Long) As LongPtr
    Private Declare PtrSafe Function SelectObject Lib "gdi32" (ByVal hDC As LongPtr, ByVal hObject As LongPtr) As LongPtr
    Private Declare PtrSafe Function DrawFrameControl Lib "user32" (ByVal hDC As LongPtr, lpRect As RECT, ByVal un1 As Long, ByVal un2 As Long) As Long
    Private Declare PtrSafe Function DeleteDC Lib "gdi32" (ByVal hDC As LongPtr) As Long
[URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=Else"]#Else[/URL] 
    Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
    Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
    Private Declare Function WindowFromAccessibleObject Lib "oleacc" (ByVal pacc As IAccessible, phwnd As Long) As Long
    Private Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    Private Declare Function DrawMenuBar Lib "user32.dll" (ByVal hwnd As Long) As Long
    Private Declare Function SetWindowPos Lib "user32" (ByVal hwnd As Long, ByVal hWndInsertAfter As Long, ByVal X As Long, ByVal Y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
    Private Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByRef lParam As Any) As Long
    Private Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
    Private Declare Function GetDeviceCaps Lib "gdi32" (ByVal hDC As Long, ByVal nIndex As Long) As Long
    Private Declare Function ReleaseDC Lib "user32" (ByVal hwnd As Long, ByVal hDC As Long) As Long
    Private Declare Function CreateSolidBrush Lib "gdi32" (ByVal crColor As Long) As Long
    Private Declare Function FrameRect Lib "user32" (ByVal hDC As Long, lpRect As RECT, ByVal hBrush As Long) As Long
    Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
    Private Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
    Private Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT) As Long
    Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
    Private Declare Function ReleaseCapture Lib "user32" () As Long
    Private Declare Function GetClientRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT) As Long
    Private Declare Function GetShellWindow Lib "user32" () As Long
    Private Declare Function GetWindowDC Lib "user32" (ByVal hwnd As Long) As Long
    Private Declare Function BitBlt Lib "gdi32" (ByVal hDestDC As Long, ByVal X As Long, ByVal Y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long
    Private Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long
    Private Declare Function ClientToScreen Lib "user32" (ByVal hwnd As Long, lpPoint As POINTAPI) As Long
    Private Declare Function IsWindowVisible Lib "user32" (ByVal hwnd As Long) As Long
    Private Declare Function IsIconic Lib "user32" (ByVal hwnd As Long) As Long
    Private Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As Long, ByVal lpProcName As String) As Long
    Private Declare Function GetNextWindow Lib "user32" Alias "GetWindow" (ByVal hwnd As Long, ByVal wFlag As Long) As Long
    Private Declare Function FreeLibrary Lib "kernel32" (ByVal hLibModule As Long) As Long
    Private Declare Function StretchBlt Lib "gdi32" (ByVal hDC As Long, ByVal X As Long, ByVal Y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal nSrcWidth As Long, ByVal nSrcHeight As Long, ByVal dwRop As Long) As Long
    Private Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hDC As Long) As Long
    Private Declare Function CreateCompatibleBitmap Lib "gdi32" (ByVal hDC As Long, ByVal nWidth As Long, ByVal nHeight As Long) As Long
    Private Declare Function SelectObject Lib "gdi32" (ByVal hDC As Long, ByVal hObject As Long) As Long
    Private Declare Function DrawFrameControl Lib "user32" (ByVal hDC As Long, lpRect As RECT, ByVal un1 As Long, ByVal un2 As Long) As Long
    Private Declare Function DeleteDC Lib "gdi32" (ByVal hDC As Long) As Long
    Private Declare Function PtInRect Lib "user32" (lpRect As RECT, ByVal X As Long, ByVal Y As Long) As Long
[URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=End"]#End[/URL]  If

[URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=If"]#If[/URL]  VBA7 Then
    Private hForm As LongPtr
    Private hMemDc As LongPtr
[URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=Else"]#Else[/URL] 
    Private hForm As Long
    Private hMemDc As Long
[URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=End"]#End[/URL]  If
 
Private Const GWL_STYLE = -16
Private Const WS_CAPTION = &HC00000
Private Const SWP_SHOWWINDOW = &H40
Private Const HORZ = 8
Private Const VERT = 10
Private Const DWMWA_CLOAKED = 14
Private Const GW_HWNDPREV = 3
Private Const HWND_TOPMOST = -1
Private Const DFC_CAPTION = 1
Private Const DFCS_CAPTIONCLOSE = &H0
Private Const WM_NCLBUTTONDOWN = &HA1
Private Const HTCAPTION = 2
Private Const SRCCOPY = &HCC0020

Private tCloseButtonRect As RECT
Private sngZoomFactor As Single, lFrameColor As Long


Private Sub IMagnifier_Show(ByVal cx As Long, ByVal cy As Long, ByVal ZoomFactor As Single, Optional ByVal FrameColor As Long)
    Dim tClientRect As RECT
    
    sngZoomFactor = ZoomFactor / 100: lFrameColor = FrameColor
    WindowFromAccessibleObject Me, hForm
    SetWindowLong hForm, GWL_STYLE, GetWindowLong(hForm, GWL_STYLE) And (Not WS_CAPTION)
    DrawMenuBar hForm
    GetClientRect hForm, tClientRect
    With tClientRect
        SetWindowPos hForm, HWND_TOPMOST, .Left, .Top, cx, cy, SWP_SHOWWINDOW
    End With
    Set cmbrs = Application.CommandBars
    Me.Show vbModeless
End Sub

Private Sub UserForm_Layout()
    UpdateMagnifier
End Sub

Private Sub UserForm_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)

    Dim tCursPos As POINTAPI
    
    If Button = 1 Then
        GetCursorPos tCursPos
         [URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=If"]#If[/URL]  VBA7 Then
                Dim lngPtr As LongPtr
                [URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=If"]#If[/URL]  Win64 Then
                    CopyMemory lngPtr, tCursPos, LenB(tCursPos)
                    If PtInRect(tCloseButtonRect, lngPtr) Then
                [URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=Else"]#Else[/URL] 
                    If PtInRect(tCloseButtonRect, tCursPos.X, tCursPos.Y) Then
                [URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=End"]#End[/URL]  If
        [URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=Else"]#Else[/URL] 
                 If PtInRect(tCloseButtonRect, tCursPos.X, tCursPos.Y) Then
        [URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=End"]#End[/URL]  If
                    Unload Me
                End If
    End If
End Sub

Private Sub UserForm_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    Call ReleaseCapture
    SendMessage hForm, WM_NCLBUTTONDOWN, HTCAPTION, 0
End Sub

Private Sub UpdateMagnifier()
    [URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=If"]#If[/URL]  VBA7 Then
        Dim hDC As LongPtr, hBrush As LongPtr
    [URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=Else"]#Else[/URL] 
        Dim hDC As Long, hBrush As Long
    [URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=End"]#End[/URL]  If

    Dim tCur As POINTAPI, tP1 As POINTAPI, tP2 As POINTAPI
    Dim tWindowRect As RECT, tClientRect As RECT

    Call CreateMemDC
    GetCursorPos tCur
    GetClientRect hForm, tClientRect
    hDC = GetDC(hForm)
    GetWindowRect hForm, tWindowRect
    
    With tWindowRect
        StretchBlt hDC, 0, 0, (.Right - .Left) * sngZoomFactor, (.Bottom - .Top) * sngZoomFactor, _
        hMemDc, .Left, .Top, (.Right - .Left), (.Bottom - .Top), SRCCOPY
    End With
    
    hBrush = CreateSolidBrush(lFrameColor)
    FrameRect hDC, tClientRect, hBrush
    DeleteObject hBrush
         
    With tCloseButtonRect
        .Bottom = 20
        .Left = tClientRect.Right - 20
        .Right = tClientRect.Right
        .Top = tClientRect.Top
    End With

    DrawFrameControl hDC, tCloseButtonRect, DFC_CAPTION, DFCS_CAPTIONCLOSE
    ReleaseDC hForm, hDC

    With tCloseButtonRect
        tP1.X = .Left: tP1.Y = .Top
        tP2.X = .Right: tP2.Y = .Bottom
        ClientToScreen hForm, tP1
        ClientToScreen hForm, tP2
        .Left = tP1.X: .Top = tP1.Y
        .Right = tP2.X: .Bottom = tP2.Y
    End With
End Sub
 
Private Sub TakeScreenShot()
    [URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=If"]#If[/URL]  VBA7 Then
        Dim hwnd As LongPtr, hDC As LongPtr, hShellDC As LongPtr
        Dim lWindowAttribute As LongPtr, hLib As LongPtr, hProc As LongPtr
    [URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=Else"]#Else[/URL] 
        Dim hwnd As Long, hDC As Long, hShellDC As Long
        Dim lWindowAttribute As Long, hLib As Long, hProc As Long
    [URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=End"]#End[/URL]  If

    Dim tWindowRect As RECT

    hwnd = GetShellWindow
    hShellDC = GetWindowDC(hwnd)
    GetWindowRect hwnd, tWindowRect

    With tWindowRect
        BitBlt hMemDc, 0, 0, .Right - .Left, .Bottom - .Top, hShellDC, 0, 0, SRCCOPY
        ReleaseDC hwnd, hShellDC
        FreeLibrary hLib
        hLib = LoadLibrary("dwmapi.dll")
        Do While hwnd <> 0
            If IsWindowVisible(hwnd) And IsIconic(hwnd) = 0 And hwnd <> hForm Then
                GetWindowRect hwnd, tWindowRect
                hDC = GetWindowDC(hwnd)
                If hLib Then
                    hProc = GetProcAddress(hLib, "DwmGetWindowAttribute")
                    If hProc Then
                        CallWindowProc hProc, hwnd, DWMWA_CLOAKED, VarPtr(lWindowAttribute), LenB(lWindowAttribute)
                        If lWindowAttribute = 0 Then
                            BitBlt hMemDc, .Left, .Top, .Right - .Left, .Bottom - .Top, hDC, 0, 0, SRCCOPY
                        End If
                    End If
                Else
                    BitBlt hMemDc, .Left, .Top, .Right - .Left, .Bottom - .Top, hDC, 0, 0, SRCCOPY
                End If
                ReleaseDC hwnd, hDC
            End If
            hwnd = GetNextWindow(hwnd, GW_HWNDPREV)
        Loop
        FreeLibrary hLib
    End With
End Sub

Private Sub CreateMemDC()
    [URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=If"]#If[/URL]  VBA7 Then
        Dim scrDc As LongPtr, hMemBmp As LongPtr
    [URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=Else"]#Else[/URL] 
        Dim scrDc As Long, hMemBmp As Long
    [URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=End"]#End[/URL]  If
    Dim lScrWidth As Long, lScrHeight As Long
    
    scrDc = GetDC(0)
    lScrWidth = GetDeviceCaps(scrDc, HORZ)
    lScrHeight = GetDeviceCaps(scrDc, VERT)
    DeleteDC hMemDc
    hMemDc = CreateCompatibleDC(scrDc)
    hMemBmp = CreateCompatibleBitmap(scrDc, lScrWidth, lScrHeight)
    SelectObject hMemDc, hMemBmp
    ReleaseDC 0, scrDc
    DeleteObject hMemBmp
    Call TakeScreenShot
End Sub

Private Sub cmbrs_OnUpdate()
    With Application.CommandBars.FindControl(ID:=2040)
        .Enabled = Not .Enabled
    End With
    Call UpdateMagnifier
End Sub

3- Code usage in a Standrad Module:
Code:
Option Explicit

Private Magnifier As IMagnifier

Public Sub Test()
    Set Magnifier = New ImpMagnifier
    Magnifier.Show Width:=350, Height:=300, ZoomFactor:=250, FrameColor:=vbRed
End Sub

As I said, this should work on 32 as well as 64 systems bit... I have written and tested the code on excel 2010 64bit Windows 10 64bit only ... so if someone can confirm that it works accross different platforms it would be great.

Regards.
 
Last edited:
Upvote 0

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top