Page 1 sur 1

Nouvelle version de la Loupe

Publié : dim. 04/juil./2004 19:11
par fweil
J'ai fait qq mises à jour sur un code développé par Franco et moi m^m il y a un certain temps déjà.

Les commentaires ne sont pas bilingues mais le prog parle plusieurs langues !

Code : Tout sélectionner

;
; Magnifier Example
;
; Franco and fweil
;
; 20040704 : revisited the whole code and added some GUI enhancements
;
; The help is changed to display an image based text with interesting splitter to fit the window. This makes an interesting workshop because the capture is threaded,
; and I had to mage concurrent drawings between the threaded capture and the help refresh when changing the language
;
; I also diminished the API calls but could not eliminate all right now. This program is still not transferable to non Windows platforms.
;
; I changed a lot of numeric constants with # constants with more clear names so that the code is easier to understand.
;
Enumeration
  #Image_Magnifier
  #Image_Help
  #MagnifierWindowID
  #MagnifierHelpWindowID
  #Image_DE
  #Image_EN
  #Image_FR
  #Image_IT
  #Image_PO
  #Image_SP
  #SF1
  #Gadget_Image
  #Font_Help
EndEnumeration

#MAX_STRING_LENGTH = 64000

;
; Color constants used for country flags
;
#MyGreen = $00A000
#MyRed = $0000E0

Language.s
Help.s
EOL.s

;
; This structure is made for string / bytes equivalence, allowing to address string characters by address
;
Structure StringBytes
  Bytes.b[#MAX_STRING_LENGTH]
EndStructure

Global Language, Help, EOL
Global CursorPosition.POINT

Global EventID.l
Global EventType.l
Global Factor.f
Global hImage.l
Global SourceDeviceContext.l
Global DestinationDeviceContext.l
Global BitMapID.l
Global Size.l
Global Quit.l
Global ViewFinder.l
Global WindowWidth.l
Global WindowHeight.l
Global OldWindowWidth.l
Global OldWindowHeight.l
Global RasterOpCode.l
Global ColorAdjustment.l
Global DestinationUpperLeftX.l
Global DestinationUpperLeftY.l
Global DestinationWidth.l
Global DestinationHeight.l
Global SourceUpperLeftX.l
Global SourceUpperLeftY.l
Global SourceWidth.l
Global SourceHeight.l
Global Copyright.l
Global GetSystemDefaultLangID.l
Global ArrowKeyPressed.l
Global OldArrowKeyPressed.l
Global MoveCursorStep.l
Global HelpFontSize.l
Global ViewFinderColor.l
Global ColorFinder.l
Global OriginX.l
Global OriginY.l
Global PixelColor.l
Global CopyBitmapToImage.l
Global CaptureThreadID.l

Global DebugS.s
Global Font.s
Global HelpFont.s
Global hWndMain.l
Global hWndHelp.l

Global ImageID_DE, ImageID_EN, ImageID_FR, ImageID_IT, ImageID_PO, ImageID_SP, ImageID_Flag, FlagXSize, FlagYSize, BackgroundImageID

;
; Flags is one of my goodies to draw country flags in the help window
; Flags are totally parametric.
; If one is interested to help me in enhacing this procedure with more flags ? !!! Nobody ?
;
Procedure Flags()
; DE
; EN
; FR
; IT
; PO
; SP
  FlagXSize = 60
  FlagYSize = 3 * FlagXSize / 4
  ImageID_DE = CreateImage(#Image_DE, FlagXSize, FlagYSize)
  StartDrawing(ImageOutput())
    Box(0, 0, FlagXSize, FlagYSize / 3, #Black)
    Box(0, FlagYSize / 3, FlagXSize, FlagYSize / 3, #MyRed)
    Box(0, 2 * FlagYSize / 3, FlagXSize, FlagYSize / 3, #Yellow)
  StopDrawing()
  
  ImageID_EN = CreateImage(#Image_EN, FlagXSize, FlagYSize)
  StartDrawing(ImageOutput())
    Box(0, 0, FlagXSize, FlagYSize, #Blue)
    For i = -FlagXSize / 18 To FlagXSize / 18
      LineXY(i, 0, i + FlagXSize, FlagYSize, #White)
      LineXY(i, FlagYSize, i + FlagXSize, 0, #White)
      LineXY(0, i + FlagYSize / 2, FlagXSize, i + FlagYSize / 2, #White)
      LineXY(i + FlagXSize / 2, 0, i + FlagXSize / 2, FlagYSize, #White)
    Next
    For i = -FlagXSize / 24 To FlagXSize / 24
      LineXY(i, 0, i + FlagXSize, FlagYSize, #Red)
      LineXY(i, FlagYSize, i + FlagXSize, 0, #Red)
      LineXY(0, i + FlagYSize / 2, FlagXSize, i + FlagYSize / 2, #Red)
      LineXY(i + FlagXSize / 2, 0, i + FlagXSize / 2, FlagYSize, #Red)
    Next
  StopDrawing()
  
  ImageID_FR = CreateImage(#Image_FR, FlagXSize, FlagYSize)
  StartDrawing(ImageOutput())
    Box(0, 0, FlagXSize / 3, FlagYSize, #Blue)
    Box(FlagXSize / 3, 0, FlagXSize / 3, FlagYSize, #White)
    Box(2 * FlagXSize / 3, 0, FlagXSize / 3, FlagYSize, #MyRed)
  StopDrawing()
  
  ImageID_IT = CreateImage(#Image_IT, FlagXSize, FlagYSize)
  StartDrawing(ImageOutput())
    Box(0, 0, FlagXSize / 3, FlagYSize, #MyGreen)
    Box(FlagXSize / 3, 0, FlagXSize / 3, FlagYSize, #White)
    Box(2 * FlagXSize / 3, 0, FlagXSize / 3, FlagYSize, #MyRed)
  StopDrawing()
  
  ImageID_PO = CreateImage(#Image_PO, FlagXSize, FlagYSize)
  StartDrawing(ImageOutput())
    Box(0, 0, FlagXSize / 3, FlagYSize, #MyGreen)
    Box(FlagXSize / 3, 0, 2 * FlagXSize / 3, FlagYSize, #MyRed)
  StopDrawing()

  ImageID_SP = CreateImage(#Image_SP, FlagXSize, FlagYSize)
  StartDrawing(ImageOutput())
    Box(0, 0, FlagXSize, 2 * FlagYSize / 9, #MyRed)
    Box(0, 2 * FlagYSize / 9, FlagXSize, 5 * FlagYSize / 9, #Yellow)
    Box(0, 7 * FlagYSize / 9, FlagXSize, 2 * FlagYSize / 9, #MyRed)
  StopDrawing()

EndProcedure

;
; A remake of my FoxLinedText that splits lines at a given length, but adapted here to split at a given pixel width.
;
; The topic is to use bytes arrays for fast string manipulation. A bit tricky but really performing routine.
;
; Well probably you know all what a fox is .... and how it can go fast to catch a chick in the henhouse !
;
Procedure.s FoxLinedText2D(StringIn.s, PixelWidth.l)
  LenStringIn = Len(StringIn)
  LenStringOut = LenStringIn + 3 * (Int(LenStringIn / PixelWidth) + 1)
  StringOut.s = Space(LenStringOut)
  *MyStringIn.StringBytes = @StringIn
  *MyStringOut.StringBytes = @StringOut
  j = 0
  For i = 0 To LenStringIn - 1
    Cod.b = *MyStringIn\Bytes[i]
    If Cod = 13 Or Cod = ' ' Or Cod = '.' Or Cod = ','
        LastWordBreakInPosition = i
        LastWordBreakOutPosition = j
        If Cod = 13
            LastLineBreak = j + 3
        EndIf
    EndIf
    If k > PixelWidth And i > 0 ; means the counter reached the right margin
        io = i
        jo = j
        i = LastWordBreakInPosition + 1
        j = LastWordBreakOutPosition
        k = 0
        *MyStringOut\Bytes[j] = 13
        *MyStringOut\Bytes[j + 1] = 10
        *MyStringOut\Bytes[j + 2] = *MyStringIn\Bytes[i] ; Asc(Mid(StringIn, i, 1))
        LastLineBreak = j + 2
        If i = LastBreakDone
            LastWordBreakInPosition = io - 1
            LastWordBreakOutPosition = jo
        EndIf
        LastBreakDone = i
        j + 2
      Else
        *MyStringOut\Bytes[j] = *MyStringIn\Bytes[i] ; Asc(Mid(StringIn, i, 1))
    EndIf
    k = TextLength(Mid(StringOut, LastLineBreak, j - LastLineBreak))
    j + 1
  Next
  *MyStringOut\Bytes[j] = 0
  ProcedureReturn StringOut
EndProcedure

Procedure CreateBackground(BackgroundXSize, BackgroundYSize)
  ProcedureReturn ImageID
EndProcedure

;
; DrawHelp() draws the country flag and the splitted text in 2D mode
;
; The help was formerly a poor gray text gadget that I changed to an image with background.
; This background is created only once.
;
Procedure DrawHelp()
  HelpWindowXSize = 480
  HelpWindowYSize = 250
  TextMaxWidth = HelpWindowXSize - FlagXSize - 30
    If BackgroundImageID = 0
        BackgroundImageID = CreateImage(#Image_Help, HelpWindowXSize, HelpWindowYSize)
        StartDrawing(ImageOutput())
          For x = 0 To HelpWindowXSize
            For y = 0 To HelpWindowYSize
              Plot(x, y, RGB(x - y, (x - y) / 3, (x - y) / 2))
            Next
          Next
        StopDrawing()
    EndIf
    
    ImageID = CreateImage(#Image_Help, HelpWindowXSize, HelpWindowYSize)
    StartDrawing(ImageOutput())
    i = 0
    y = 8
    DrawingMode(1)
    DrawingFont(LoadFont(#Font_Help, HelpFont, HelpFontSize, #PB_Font_HighQuality | #PB_Font_Bold))
    BackColor(0, 0, 0)
    FrontColor(255, 255, 255)
    c$ = FoxLinedText2D(Help, TextMaxWidth)
    Repeat
      iu = FindString(c$, EOL, 1)
      If iu
          a$ = Mid(c$, 1, iu - 1)
          c$ = Mid(c$, iu + 2, Len(c$) - iu - 2 + 1)
          If Left(a$, 1) = Chr(10)
              a$ = Right(a$, Len(a$) - 1)
          EndIf
          Locate(10, y)
          DrawText(a$)
          y + 12
      EndIf
    Until c$ = ""
    DrawImage(ImageID_Flag, 480 - FlagXSize - 2, 2)
  StopDrawing()
  ProcedureReturn ImageID
EndProcedure

;
; Translator returns a translated message according to Language
;
Procedure.s Translator(message.s)
  Select message
    Case "Magnifier"
      Select Language
        Case "DE"
          message = "Lupe"
        Case "EN"
          message = "Loupe"
        Case "FR"
          message = "Loupe"
        Case "IT"
          message = "Lente d'ingrandimento"
        Case "PO"
          message = "Lupa"
        Case "SP"
          message = "Lupa"
        Default
      EndSelect
    Case "Magnifier help"
      Select Language
        Case "DE"
          message = "Lupe Hilfe"
        Case "EN"
          message = "Loupe Help"
        Case "FR"
          message = "Aide de la Loupe"
        Case "IT"
          message = "Lente Aiuto"
        Case "PO"
          message = "Lupa Ajuda"
        Case "SP"
          message = "Lupa ayuda"
        Default
      EndSelect
    Default
      Select Language
        Case "DE"
          message = "Unbekannte Antwort"
        Case "EN"
          message = "Unknown message"
        Case "FR"
          message = "Message inconnu"
        Case "IT"
          message = "Messaggio sconosciuto"
        Case "PO"
          message = "Mensagem desconhecida"
        Case "SP"
          message = "Respuesta desconocida"
        Default
          message = "Unknown message"
      EndSelect
  EndSelect
  ProcedureReturn message
EndProcedure


;
; LoadHelp loads the localized help
; If one can help to embed this or add languages ? Does one can do something ?
;
Procedure LoadHelp()
  Select Language
    ;@Francois: Translation not polished yet (DE/IT)
    Case "DE"
      Help = ""
      Help = Help + "Zahlenblock - : Vergroesserung nimmt kontinuierlich ab / Zahlenblock + : Vergroesserung nimmt kontinuierlich zu" + EOL
      Help = Help + "Vergroesserung : F2 = 0.5 / F3 = 1 / F4 = 2 / F5 = 4 / F6 = 8 / F7 = 16 / F8 = 32" + EOL
      Help = Help + "Groesse : F9 = 100 / F10 = 200 / F11 = 320 / F12 = 640" + EOL
      Help = Help + "Pos 1 : Sucher anzeigen - verstecken" + EOL
      Help = Help + "Bild Hoch - Bild Runter : Wechsel die Farbe des Suchers" + EOL
      Help = Help + "C : Farbe Sucher anzeigen - verstecken" + EOL
      Help = Help + "------------------------------------------------------" + EOL
      ;@Francois: is 'Illumnant A' -> 'Illuminant'?
      ; it's not the same as 'Brightness' ? 
      ; well there is 'Contrast' but these functions are not working right now (I suppose) so I can't figure it out.
      Help = Help + "E : Positiv / R : Negativ / S : Halbton / D : Illuminant  A / " + EOL
      Help = Help + "F : Helligkeit -100 / G : Helligkeit -50 / H : Helligkeit 0 / J : Helligkeit 50 / K : Helligkeit 100" + EOL
      Help = Help + "------------------------------------------------------" + EOL
      Help = Help + "F1 : Hilfe anzeigen - verstecken / B : Bild abspeichern / L : ändern program's Sprache" + EOL
      Help = Help + "Escape Taste oder Beenden Knopf : Beenden" + EOL
      Help = Help + "Sie können das Magnifier verschieben, indem Sie es mit der links Maustaste schleppen" + EOL
      Help = Help + "------------------------------------------------------" + EOL
      Help = Help + "Benutze die Schnappschuss Tasten um das Fenster oder das Bildschirm in den clipboard zu kopieren" + EOL
      Help = Help + "Pfeile dürfen den Cursor genau verschieben" + EOL
      Help = Help + "Behalten Sie den Schlüssel um Cursor-Bewegung zu beschleunigen" + EOL
      ImageID_Flag = ImageID_DE
    Case "EN"
      Help = ""
      Help = Help + "NumPad - : Magnify continuous decrease / NumPad + : Magnify continuous increase" + EOL
      Help = Help + "Increase : F2 = 0.5 / F3 = 1 / F4 = 2 / F5 = 4 / F6 = 8 / F7 = 16 / F8 = 32" + EOL
      Help = Help + "Size : F9 = 100 / F10 = 200 / F11 = 320 / F12 = 640" + EOL
      Help = Help + "Home : Show - hide Viewfinder" + EOL
      Help = Help + "PageUp - PageDown : Change viewfinder color" + EOL
      Help = Help + "C : Show - hide color finder" + EOL
      Help = Help + "------------------------------------------------------" + EOL
      Help = Help + "E : Positive / R : Negative / S : Halftone / D : Illuminant A / " + EOL
      Help = Help + "F : Brightness -100 / G : Brightness -50 / H : Brightness 0 / J : Brightness 50 / K : Brightness 100" + EOL
      Help = Help + "------------------------------------------------------" + EOL
      Help = Help + "F1 : Show - hide Help / B : Save image to file / L : Change program's language" + EOL
      Help = Help + "Escape or close gadget : Exit" + EOL
      Help = Help + "You can move the Magnifier window by dragging it with the left mouse button" + EOL
      Help = Help + "------------------------------------------------------" + EOL
      Help = Help + "Use snapshot keys to put the window or screen into the clipboard" + EOL
      Help = Help + "Arrow keys allow to move the cursor accurately" + EOL
      Help = Help + "Maintain key pressed to accelerate cursor move" + EOL
      ImageID_Flag = ImageID_EN
    Case "FR"
      Help = ""
      Help = Help + "NumPad - : zoom inverse progressif / NumPad + : zoom progressif" + EOL
      Help = Help + "Grossissement : F2 = 0,5 / F3 = 1 / F4 = 2 / F5 = 4 / F6 = 8 / F7 = 16 / F8 = 32" + EOL
      Help = Help + "Taille : F9 = 100 / F10 = 200 / F11 = 320 / F12 = 640" + EOL
      Help = Help + "Début : Afficher - masquer le réticule" + EOL
      Help = Help + "PageUp - PageDown : Changer la couleur du réticule" + EOL
      Help = Help + "C : Afficher - masquer la capture de couleur" + EOL
      Help = Help + "------------------------------------------------------" + EOL
      Help = Help + "E : Positif / R : Négatif / S : Halftone / D : Illuminant A / " + EOL
      Help = Help + "F : Luminosité -100 / G : Luminosité -50 / H : Luminosité 0 / J : Luminosité 50 / K : Luminosité 100" + EOL
      Help = Help + "------------------------------------------------------" + EOL
      Help = Help + "F1 : Afficher - masquer l'aide / B : Enregistrer l'image / L : Changer la langue du programme" + EOL
      Help = Help + "Echap. ou Fermer : Fin" + EOL
      Help = Help + "Vous pouvez déplacer la fenêtre Magnifier en la glissant avec le bouton gauche de la souris" + EOL
      Help = Help + "------------------------------------------------------" + EOL
      Help = Help + "Utilisez les touches de copie d'écran pour placer l'écran ou la fenêtre dans le presse papier" + EOL
      Help = Help + "Les flèches permettent de déplacer le curseur avec la plus grande précision" + EOL
      Help = Help + "Maintenir la touche appuyée permet d'accélérer le mouvement du curseur" + EOL
      ImageID_Flag = ImageID_FR
    Case "IT"
      Help = ""     
      Help = Help + "Tasterino numerico - : L'ingrandimento ridurre continuamente / Tasterino numerico + : L'ingrandimento aumenta continuamente" + EOL
      Help = Help + "Ingrandimento : F2 = 0.5 / F3 = 1 / F4 = 2 / F5 = 4 / F6 = 8 / F7 = 16 / F8 = 32 " + EOL
      Help = Help + "Dimensione : F9 = 100 / F10 = 200 / F11 = 320 / F12 = 640" + EOL
      Help = Help + "Inizio : Mostri - nasconda il mirino" + EOL ;??? Spazio? ;??? Home ? What is there on the key?
      Help = Help + "PageUp & PageDown : Cambia il colore del Mirino" + EOL
      Help = Help + "C : Mostri - nasconda il cercatore di colore" + EOL
      Help = Help + "------------------------------------------------------" + EOL
      Help = Help + "E : Positivo / R : Negativo / S : Semitono / D : Illuminante A / " + EOL
      Help = Help + "F : Luminosità -100 / G : Luminosità -50 / H : Luminosità 0 / J : Luminosità 50 / K : Luminosità 100" + EOL
      Help = Help + "------------------------------------------------------" + EOL
      Help = Help + "F1 : Mostri - nasconda aiuto / B : risparmi l'immagine alla lima / L : cambi la lingua dell'applicazione" + EOL
      Help = Help + "ESC oppure  or close gadget : Exit" + EOL
      Help = Help + "Potete spostare la finestra del Magnifier trascinandola con il tasto di mouse di sinistra" + EOL
      Help = Help + "------------------------------------------------------" + EOL
      Help = Help + "Usi i tasti di fotografia istantanea per copiare la finestra o schermo nel 'clipboard'" + EOL ;??? oh boy!
      Help = Help + "Le frecce concedono spostare esattamente il cursore" + EOL
      Help = Help + "Effettui la chiave premuta accelerano il movimento del cursore" + EOL
      ImageID_Flag = ImageID_IT
    Case "PO"
      Help = ""
      Help = Help + "NumPad - : Amplie a diminuição contínua / NumPad + : Amplie o aumento contínuo" + EOL
      Help = Help + "Amplie : F2 = 0,5 / F3 = 1 / F4 = 2 / F5 = 4 / F6 = 8 / F7 = 16 / F8 = 32" + EOL
      Help = Help + "Tamanho : F9 = 100 / F10 = 200 / F11 = 320 / F12 = 640 " + EOL
      Help = Help + "Empezar : Mostre - esconda visor" + EOL
      Help = Help + "PageUp - PageDown : Mudar visor cores" + EOL
      Help = Help + "C : Mostre - esconda ferramenta da cor" + EOL
      Help = Help + "------------------------------------------------------" + EOL
      Help = Help + "E : Positivo / R : Negativo / S : Tonalidad / D : Illumnant A / " + EOL
      Help = Help + "F : Brilho -100 / G : Brilho -50 / H : Brilho 0 / J : Brilho 50 / K : Brilho 100" + EOL
      Help = Help + "------------------------------------------------------" + EOL
      Help = Help + "F1 : Mostre - esconda ajuda / B : excepto a imagem à lima / L : mude a língua da aplicação" + EOL
      Help = Help + "Esc. o cerrar : Saída" + EOL
      Help = Help + "Você pode mover a janela do Magnifier arrastando a com a tecla de rato esquerda" + EOL
      Help = Help + "------------------------------------------------------" + EOL
      Help = Help + "Use as chaves do 'snapshot' colocar a tela ou a janela no 'clipboard'" + EOL
      Help = Help + "As setas reservam para mover exatamente o cursor" + EOL
      Help = Help + "Mantenha a chave pressionada aceleram o movimento do cursor" + EOL
      ImageID_Flag = ImageID_PO
    Case "SP"
      Help = ""
      Help = Help + "NumPad - : zoom reverso progressivo / NumPad + : zoom progressivo" + EOL
      Help = Help + "Zoom : F2 = 0,5 / F3 = 1 / F4 = 2 / F5 = 4 / F6 = 8 / F7 = 16 / F8 = 32" + EOL
      Help = Help + "Talla : F9 = 100 / F10 = 200 / F11 = 320 / F12 = 640" + EOL
      Help = Help + "Empezar : Demuestre - oculte el visor" + EOL
      Help = Help + "PageUp - PageDown : Change viewfinder color" + EOL
      Help = Help + "C : Demuestre - oculte herramienta del color" + EOL
      Help = Help + "------------------------------------------------------" + EOL
      Help = Help + "E : Positivo / R : Negativo / S : Tonalidad / D : Illumnant A / " + EOL
      Help = Help + "F : Luminoso -100 / G : Luminoso -50 / H : Luminoso 0 / J : Luminoso 50 / K : Luminoso 100" + EOL
      Help = Help + "------------------------------------------------------" + EOL
      Help = Help + "F1 : Demuestre - oculte ayuda / B : excepto imagen al archivo / L : cambie la lengua del uso" + EOL
      Help = Help + "Esc. o cerrar : Terminar" + EOL
      Help = Help + "Usted puede mover la ventana de la lupa arrastrándola con el botón de ratón izquierdo" + EOL
      Help = Help + "------------------------------------------------------" + EOL
      Help = Help + "Utilice las llaves del 'snapshot' para colocar la pantalla o la ventana en el 'clipboard'" + EOL
      Help = Help + "Las flechas permiten para mover el cursor exactamente" + EOL
      Help = Help + "Mantenga la llave presionada aceleran movimiento del cursor" + EOL
      ImageID_Flag = ImageID_SP
    Default
      Help = ""
      Help = Help + "NumPad - : Magnify continuous decrease / NumPad + : Magnify continuous increase" + EOL
      Help = Help + "Increase : F2 = 0.5 / F3 = 1 / F4 = 2 / F5 = 4 / F6 = 8 / F7 = 16 / F8 = 32" + EOL
      Help = Help + "Size : F9 = 100 / F10 = 200 / F11 = 320 / F12 = 640" + EOL
      Help = Help + "Home : Show - hide Viewfinder" + EOL
      Help = Help + "PageUp - PageDown : Change viewfinder color" + EOL
      Help = Help + "C : Show - hide color finder" + EOL
      Help = Help + "------------------------------------------------------" + EOL
      Help = Help + "E : Positive / R : Negative / S : Halftone / D : Illuminant A / " + EOL
      Help = Help + "F : Brightness -100 / G : Brightness -50 / H : Brightness 0 / J : Brightness 50 / K : Brightness 100" + EOL
      Help = Help + "------------------------------------------------------" + EOL
      Help = Help + "F1 : Show - hide Help / B : Save image to file / L : Change program's language" + EOL
      Help = Help + "Escape or close gadget : Exit" + EOL
      Help = Help + "You can move the Magnifier window by dragging it with the left mouse button" + EOL
      Help = Help + "------------------------------------------------------" + EOL
      Help = Help + "Use snapshot keys to put the window or screen into the clipboard" + EOL
      Help = Help + "Arrow keys allow to move the cursor accurately" + EOL
      Help = Help + "Maintain key pressed to accelerate cursor move" + EOL
      ImageID_Flag = ImageID_EN
  EndSelect
  ProcedureReturn
EndProcedure

;
; AcquireImage gets the SourceDeviceContext bitmap and puts it in DestinationDeviceContext
; Then it draws the image
;
; This make the image capture independant from the drawing output.
;
Procedure.l AcquireImage()
  FileName.s
    GetCursorPos_(CursorPosition)
    SourceDeviceContext = GetDC_(0)
    PixelColor = GetPixel_(SourceDeviceContext, CursorPosition\x, CursorPosition\y)
    DestinationDeviceContext = CreateCompatibleDC_(SourceDeviceContext)
    BitMapID = CreateImage(#Image_Magnifier, WindowWidth, WindowHeight)
    SelectObject_(DestinationDeviceContext, BitMapID)
    DestinationUpperLeftX = 0
    DestinationUpperLeftY = 0
    DestinationWidth = WindowWidth
    DestinationHeight = WindowHeight
    SourceUpperLeftX = CursorPosition\x - Int(WindowWidth / Factor) >> 1
    SourceUpperLeftY = CursorPosition\y - Int(WindowHeight / Factor) >> 1
    ;
    ; OK ... just read the MS Windows documentation !
    ;
    SetStretchBltMode_(DestinationDeviceContext, ColorAdjustment)
    StretchBlt_(DestinationDeviceContext, DestinationUpperLeftX, DestinationUpperLeftY, DestinationWidth, DestinationHeight, SourceDeviceContext, SourceUpperLeftX, SourceUpperLeftY, SourceWidth, SourceHeight, RasterOpCode)
    DeleteDC_(DestinationDeviceContext)
    ReleaseDC_(0, SourceDeviceContext)
    DrawImage(BitMapID, 0, 0)
    ;
    ; If the CopyBitmapToImage signal is #TRUE open a SaveFileRequester to save the bitmap
    ; in bmp 24b
    ;
    If CopyBitmapToImage
        FileName = SaveFileRequester("Choose a file name", "C:\*.bmp", "", 0)
        If FileName <> ""
            SaveImage(#Image_Magnifier, FileName)
        EndIf
        CopyBitmapToImage = #FALSE
    EndIf
    
    DeleteObject_(BitMapID)
    ProcedureReturn
EndProcedure

Procedure SetViewFinder()
  ;
  ; Add a viewfinder if option selected
  ;
  If ViewFinder
      ;
      ; Set DrawingMode to 1 for transparency drawing
      ;
      DrawingMode(1)
      ;
      ; Draw the viewfinder
      ;
      Line (WindowWidth >> 1, 0, 0, WindowHeight, ViewFinderColor) ;vertical
      Line (0, WindowHeight >> 1, WindowWidth, 0, ViewFinderColor) ;horizontal
      ;
      ; Lets make a target... using DrawingMode 4 to draw an empty transparent square
      ;
      DrawingMode(4)
      Box(WindowWidth >> 1 - Int(1 * Factor) >> 1, WindowHeight >> 1 - Int(1 * Factor) >> 1, Factor, Factor, ViewFinderColor)
      ;
      ; Update pointer coordinates
      ;
      DrawingMode(0)
      SetWindowText_(WindowID(#MagnifierWindowID), "X " + Str(CursorPosition\x - OriginX) + " , Y " + Str(CursorPosition\y - OriginY))
    Else
      ;
      ; When not in ViewFinder mode just display this message
      ;
      SetWindowText_(WindowID(#MagnifierWindowID), Translator("Magnifier") + " - " + Language)
  EndIf
EndProcedure

Procedure SetColorFinder()
  ;
  ; ColorFinder adds current pixel's RGB values if option selected
  ;
  If ColorFinder
      a$ = "RGB=(" + Str(Red(PixelColor)) + "," + Str(Green(PixelColor)) + "," + Str(Blue(PixelColor)) + ")"
      a$ = a$ + Space(20 - Len(a$))
      a$ = a$ + " - " + "#" + RSet(Hex(Red(PixelColor)), 2, "0") + RSet(Hex(Green(PixelColor)), 2, "0") + RSet(Hex(Blue(PixelColor)), 2, "0")
      SetWindowTitle(#MagnifierWindowID, a$)
  EndIf
EndProcedure

Procedure SetCopyright()
  ;
  ; Add a watermark if selected (to lock on a possible license file or key)
  ;
  If Copyright
      DrawingMode(1 | 2)
      Locate(WindowWidth >> 3, WindowHeight - WindowWidth >> 4)
      DrawText("(c) fsw@attbi.com & fw@nasca.fr")
      DrawingMode(0)
  EndIf
EndProcedure

;
; Thread Procedure for the capturing, this way we can adjust the Image 
; to the actual size while resizing with the mouse...
;
Procedure Capture(NotUsed)
  Repeat
    Delay(20)
        ;
        ; Pixel captio around the cursor position and copy / transform in the Magnifier window
        ;
        ; The concept is to get pixels from source frame to draw it in destination frame
        ;
        ; Magnifying means making the source smaller ... the destination size does not change (except if destination
        ; window size changes).
        ;
        AcquireImage()
        SetViewFinder()
        SetColorFinder()
        SetCopyright()
        ;
        ; To never forget why those two lines : just to make an odd pixel number !
        ;
        WindowWidth = WindowWidth() >> 1 << 1 + 1
        WindowHeight = WindowHeight() >> 1 << 1 + 1
        ;
        ; Checks if width or height of the window were changed and keep the window squared
        ; Also changes font size if necessary
        ;
        If WindowWidth <> OldWindowWidth
            ;
            ; WindowWidth is 121 pixel lower limit
            ; This way the window can't be a rectangle if minimized smaller than 121
            ;
            If WindowWidth < 121
                WindowWidth = 121
            EndIf
            DrawingFont(LoadFont(0, Font, WindowWidth >> 5))
            SourceWidth = Int(WindowWidth / Factor) >> 1 << 1 + 1
            SourceHeight = Int(WindowHeight / Factor) >> 1 << 1 + 1
            OldWindowWidth = WindowWidth
            OldWindowHeight = WindowHeight
            ;
            ; in this way a pixel is always a square not a rectangle...
            ;
        EndIf

        If WindowHeight <> OldWindowHeight
            ;
            ; WindowHeight has no lower limit but as WindowWidth does ... !
            ; This way the window can't be a rectangle if minimized smaller than 121
            ;
            If WindowHeight < 121
                WindowHeight = 121
            EndIf
            DrawingFont(LoadFont(0, Font, WindowWidth >> 5))
            SourceWidth = Int(WindowWidth / Factor) >> 1 << 1 + 1
            SourceHeight = Int(WindowHeight / Factor) >> 1 << 1 + 1
            OldWindowWidth = WindowWidth
            OldWindowHeight = WindowHeight
            
            ;
            ; in this way a pixel is always a square not a rectangle...
            ;
        EndIf
        
        ;
        ; if the user changes the focus to the help window we put the focus back on the main window
        ; like to have the shortcuts available either way
        ;
        If GetFocus_() = WindowID(#MagnifierHelpWindowID)
          UseWindow(#MagnifierWindowID)
          ActivateWindow()
        EndIf
        ;
        ; This is the cursor move accelerator when the user maintains an arrow key pushed
        ;
        ; Because using a threaded capture procedure, this feature cannot work like before. I added
        ; a time differential calculation to cumulate more events and make it work fine.
        ;
        ; The delay should not be to far from thread main delay. I sat the main delay to 20ms and this
        ; one to 50. A longer delay here would make the accelerator grow to fast. A shorter would
        ; cause some slow down effect if using a large screen capture (because of time the capture
        ; takes).
        ;
        
        If GetTickCount_() - tz > 50
            tz = GetTickCount_()
            If OldArrowKeyPressed = ArrowKeyPressed
                ArrowKeyPressed = 0
                MoveCursorStep = 1
              Else
                MoveCursorStep = 1 + ArrowKeyPressed >> 2
            EndIf
            OldArrowKeyPressed = ArrowKeyPressed
        EndIf

  ForEver
EndProcedure

;
; Main starts here
;
FileName.s
HelpFlag.l

  ViewFinderColor = #Red
  RasterOpCode = #SRCCOPY
  EOL = Chr(13) + Chr(10)
  Quit = #FALSE
  Copyright = #TRUE
  Font = "Gill Sans Ultra Bold"
  HelpFont = "Verdana"
  HelpFontSize = 7
  HelpFlag = #FALSE

  Language = "EN"
  
  ;
  ; Set cursor displacement when using arrow keys
  ;
  MoveCursorStep = 1

  GetSystemDefaultLangID = GetSystemDefaultLangID_()
  ;
  ; Language support allows
  ;
  ; EN    english / neutral / default / USA / UK / Australia / Canada / New Zealand / Ireland / South Africa / Jamaica / Carribean / Belize / Trinidad
  ; DK    danish
  ; DE    german / Standard
  ; GR    greek
  ; SP    spanish / Traditional / Modern
  ; FI    Finnish
  ; FR    French / Standard
  ; IT    Italian / Standard
  ; NL    Dutch / Standard / Belgian
  ; NO    Norwegian / Bokmal
  ; PL    Polish
  ; PO    Portuguese / Standard
  ; RU    Russian
  ;
  ; All undefined will be set to EN or to Default in Select structures
  ;
  Select GetSystemDefaultLangID
    Case 0      ; = Language Neutral
      Language = "EN"
    Case 1024   ; = Process Default Language
      Language = "EN"
    Case 1030   ; = Danish
      Language = "DK"
    Case 1031   ; = German (Standard)
      Language = "DE"
    Case 1032   ; = Greek
      Language = "GR"
    Case 1033   ; = English (United States)
      Language = "EN"
    Case 2057   ; = English (United Kingdom)
      Language = "EN"
    Case 3081   ; = English (Australian)
      Language = "EN"
    Case 4105   ; = English (Canadian)
      Language = "EN"
    Case 5129   ; = English (New Zealand)
      Language = "EN"
    Case 6153   ; = English (Ireland)
      Language = "EN"
    Case 7177   ; = English (South Africa)
      Language = "EN"
    Case 8201   ; = English (Jamaica)
      Language = "EN"
    Case 9225   ; = English (Caribbean)
      Language = "EN"
    Case 10249  ; = English (Belize)
      Language = "EN"
    Case 11273  ; = English (Trinidad)
      Language = "EN"
    Case 1034   ; = Spanish (Traditional Sort)
      Language = "SP"
    Case 3082   ; = Spanish (Modern Sort)
      Language = "SP"
    Case 1035   ; = Finnish
      Language = "FI"
    Case 1036   ; = French (Standard)
      Language = "FR"
    Case 1040   ; = Italian (Standard)
      Language = "IT"
    Case 1043   ; = Dutch (Standard)
      Language = "NL"
    Case 2067   ; = Dutch (Belgian)
      Language = "NL"
    Case 1044   ; = Norwegian (Bokmal)
      Language = "NO"
    Case 2068   ; = Norwegian (Nynorsk)
      Language = "NO"
    Case 1045   ; = Polish
      Language = "PL"
    Case 2070   ; = Portuguese (Standard)
      Language = "PO"
    Case 1049   ; = Russian
      Language = "RU"
    Default
      Language = "EN"
  EndSelect

  Flags()
  LoadHelp()

  Factor = 2

  WindowWidth = 201
  WindowHeight = 201

  ;
  ; Create a window for help
  ;
  hWndHelp = OpenWindow(#MagnifierHelpWindowID, 200, 425, 480, 250, #PB_Window_Borderless, Translator("Magnifier help"))
  If hWndHelp
    CreateGadgetList(WindowID(#MagnifierHelpWindowID))
    ImageGadget(#Gadget_Image, 0, 0, 480, 250, DrawHelp())
    HideWindow(#MagnifierHelpWindowID, 1)
  EndIf
  ;
  ; Create the main magnifier window
  ;
  hWndMain = OpenWindow(#MagnifierWindowID, 200, 200, WindowWidth, WindowHeight, #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget | #PB_Window_SizeGadget | #PB_Window_TitleBar, Translator("Magnifier"))
  If hWndMain
    SetWindowPos_(WindowID(#MagnifierWindowID),#HWND_TOPMOST,200, 200, WindowWidth, WindowHeight, #SWP_NOACTIVATE | #SWP_NOSIZE | #SWP_NOMOVE )
      ;
      ; Change the cursor to Crosshair inside the Magnifier window
      ;
      SetClassLong_(WindowID(#MagnifierWindowID),#GCL_HCURSOR,LoadCursor_(0,#IDC_CROSS))

      ;
      ; Enable all shortcuts for the main Window
      ;
      AddKeyboardShortcut(#MagnifierWindowID, #PB_Shortcut_F1        ,  #PB_Shortcut_F1)
      AddKeyboardShortcut(#MagnifierWindowID, #PB_Shortcut_F2        ,  #PB_Shortcut_F2)
      AddKeyboardShortcut(#MagnifierWindowID, #PB_Shortcut_F3        ,  #PB_Shortcut_F3)
      AddKeyboardShortcut(#MagnifierWindowID, #PB_Shortcut_F4        ,  #PB_Shortcut_F4)
      AddKeyboardShortcut(#MagnifierWindowID, #PB_Shortcut_F5        ,  #PB_Shortcut_F5)
      AddKeyboardShortcut(#MagnifierWindowID, #PB_Shortcut_F6        ,  #PB_Shortcut_F6)
      AddKeyboardShortcut(#MagnifierWindowID, #PB_Shortcut_F7        ,  #PB_Shortcut_F7)
      AddKeyboardShortcut(#MagnifierWindowID, #PB_Shortcut_F8        ,  #PB_Shortcut_F8)
      AddKeyboardShortcut(#MagnifierWindowID, #PB_Shortcut_F9        ,  #PB_Shortcut_F9)
      AddKeyboardShortcut(#MagnifierWindowID, #PB_Shortcut_F10       , #PB_Shortcut_F10)
      AddKeyboardShortcut(#MagnifierWindowID, #PB_Shortcut_F11       , #PB_Shortcut_F11)
      AddKeyboardShortcut(#MagnifierWindowID, #PB_Shortcut_F12       , #PB_Shortcut_F12)
      AddKeyboardShortcut(#MagnifierWindowID, #PB_Shortcut_Home    , #PB_Shortcut_Home)
      AddKeyboardShortcut(#MagnifierWindowID, #PB_Shortcut_Prior      , #PB_Shortcut_Prior)
      AddKeyboardShortcut(#MagnifierWindowID, #PB_Shortcut_Next      , #PB_Shortcut_Next)
      AddKeyboardShortcut(#MagnifierWindowID, #PB_Shortcut_Insert    , #PB_Shortcut_Insert)
      AddKeyboardShortcut(#MagnifierWindowID, #PB_Shortcut_Left       , #PB_Shortcut_Left)
      AddKeyboardShortcut(#MagnifierWindowID, #PB_Shortcut_Up         , #PB_Shortcut_Up)
      AddKeyboardShortcut(#MagnifierWindowID, #PB_Shortcut_Right     , #PB_Shortcut_Right)
      AddKeyboardShortcut(#MagnifierWindowID, #PB_Shortcut_Down     , #PB_Shortcut_Down)
      AddKeyboardShortcut(#MagnifierWindowID, #PB_Shortcut_Subtract , #PB_Shortcut_Subtract)
      AddKeyboardShortcut(#MagnifierWindowID, #PB_Shortcut_Add       , #PB_Shortcut_Add)
      AddKeyboardShortcut(#MagnifierWindowID, #PB_Shortcut_Escape   , #PB_Shortcut_Escape)
      AddKeyboardShortcut(#MagnifierWindowID, #PB_Shortcut_E           ,#PB_Shortcut_E)
      AddKeyboardShortcut(#MagnifierWindowID, #PB_Shortcut_R           ,#PB_Shortcut_R)
      AddKeyboardShortcut(#MagnifierWindowID, #PB_Shortcut_S           ,#PB_Shortcut_S)
      AddKeyboardShortcut(#MagnifierWindowID, #PB_Shortcut_D           ,#PB_Shortcut_D)
      AddKeyboardShortcut(#MagnifierWindowID, #PB_Shortcut_F            ,#PB_Shortcut_F)
      AddKeyboardShortcut(#MagnifierWindowID, #PB_Shortcut_G           ,#PB_Shortcut_G)
      AddKeyboardShortcut(#MagnifierWindowID, #PB_Shortcut_H           ,#PB_Shortcut_H)
      AddKeyboardShortcut(#MagnifierWindowID, #PB_Shortcut_J            ,#PB_Shortcut_J)
      AddKeyboardShortcut(#MagnifierWindowID, #PB_Shortcut_K           ,#PB_Shortcut_K)
      AddKeyboardShortcut(#MagnifierWindowID, #PB_Shortcut_L            ,#PB_Shortcut_L)
      AddKeyboardShortcut(#MagnifierWindowID, #PB_Shortcut_C           ,#PB_Shortcut_C)
      AddKeyboardShortcut(#MagnifierWindowID, #PB_Shortcut_B           ,#PB_Shortcut_B)
      AddKeyboardShortcut(#MagnifierWindowID, #PB_Shortcut_F1 | #PB_Shortcut_Shift, #SF1)
    Else
      End
  EndIf
  StartDrawing(WindowOutput())

  SourceWidth = Int(WindowWidth / Factor) >> 1 << 1 + 1
  SourceHeight = Int(WindowHeight / Factor) >> 1 << 1 + 1
  
  
  CaptureThreadID = CreateThread(@Capture(),NotUsed)

  ;
  ; Here is the events loop
  ;
  Repeat
  
    ;
    ; The repeat / until loop is windowevent based with a delay to not consume CPU
    ;
    Select WaitWindowEvent()
      ;
      ; Separate entry point for window close gadget
      ;
      Case #PB_EventCloseWindow
        Quit = #TRUE
      ;
      ; Following events are locked to EventMenuID()
      ;
      Case #PB_EventMenu
        Select EventMenuID()
          Case #PB_Shortcut_F1                                                 ; F1           Show / hide help
            HelpFlag = 1 - HelpFlag
            If HelpFlag
                MagnifierHelpWindowPos.RECT
                GetWindowRect_(WindowID(#MagnifierHelpWindowID), MagnifierHelpWindowPos)
                HideWindow(#MagnifierHelpWindowID, 0)
                MagnifierWindowPos.RECT
                GetWindowRect_(WindowID(#MagnifierWindowID), MagnifierWindowPos)
                SetWindowPos_(WindowID(#MagnifierHelpWindowID), #HWND_TOPMOST, MagnifierWindowPos\left, MagnifierWindowPos\bottom, MagnifierHelpWindowPos\right - MagnifierHelpWindowPos\left, MagnifierHelpWindowPos\bottom - MagnifierHelpWindowPos\top, 0)
                UseWindow(#MagnifierWindowID)
                ActivateWindow()
              Else
                HideWindow(#MagnifierHelpWindowID, 1)
            EndIf
          Case #PB_Shortcut_F2                                                 ; F2           Factor 0.5
            Factor = 0.5
            SourceWidth = Int(WindowWidth / Factor) >> 1 << 1 - 1
            SourceHeight = Int(WindowHeight / Factor) >> 1 << 1 - 1
          Case #PB_Shortcut_F3                                                 ; F3           Factor 1
            Factor = 1
            SourceWidth = Int(WindowWidth / Factor) >> 1 << 1 + 1
            SourceHeight = Int(WindowHeight / Factor) >> 1 << 1 + 1
          Case #PB_Shortcut_F4                                                 ; F4           Factor 2
            Factor = 2
            SourceWidth = Int(WindowWidth / Factor) >> 1 << 1 + 1
            SourceHeight = Int(WindowHeight / Factor) >> 1 << 1 + 1
          Case #PB_Shortcut_F5                                                 ; F5           Factor 4
            Factor = 4
            SourceWidth = Int(WindowWidth / Factor) >> 1 << 1 + 1
            SourceHeight = Int(WindowHeight / Factor) >> 1 << 1 + 1
          Case #PB_Shortcut_F6                                                 ; F6           Factor 8
            Factor = 8
            SourceWidth = Int(WindowWidth / Factor) >> 1 << 1 + 1
            SourceHeight = Int(WindowHeight / Factor) >> 1 << 1 + 1
          Case #PB_Shortcut_F7                                                 ; F7           Factor 16
            Factor = 16
            SourceWidth = Int(WindowWidth / Factor) >> 1 << 1 + 1
            SourceHeight = Int(WindowHeight / Factor) >> 1 << 1 + 1
          Case #PB_Shortcut_F8                                                 ; F8           Factor 32
            Factor = 32
            SourceWidth = Int(WindowWidth / Factor) >> 1 << 1 + 1
            SourceHeight = Int(WindowHeight / Factor) >> 1 << 1 + 1
          Case #PB_Shortcut_F9                                                 ; F9           Window size 121
            If WindowHeight = 121
               ;Nothing to do... 
            Else
              WindowWidth = 121
              WindowHeight = 121
              ResizeWindow(WindowWidth, WindowHeight)
              DrawingFont(LoadFont(0, Font, WindowWidth >> 5))
            EndIf
          Case #PB_Shortcut_F10                                                ; F10          Window size 241
            If WindowHeight = 241
              ;Nothing to do... 
            Else
              WindowWidth = 241
              WindowHeight = 241
              ResizeWindow(WindowWidth, WindowHeight)
              DrawingFont(LoadFont(0, Font, WindowWidth >> 5))
            EndIf
          Case #PB_Shortcut_F11                                                ; F11          Window size 361
            If WindowHeight = 361
              ;Nothing to do... 
            Else
              WindowWidth = 361
              WindowHeight = 361
              ResizeWindow(WindowWidth, WindowHeight)
              DrawingFont(LoadFont(0, Font, WindowWidth >> 5))
            EndIf
          Case #PB_Shortcut_F12                                                ; F12          Window size 481
            If WindowHeight = 481
              ;Nothing to do... 
            Else
              WindowWidth = 481
              WindowHeight = 481
              ResizeWindow(WindowWidth, WindowHeight)
              DrawingFont(LoadFont(0, Font, WindowWidth >> 5))
            EndIf
          Case #PB_Shortcut_Home                                               ; Home         Start / Stop measurement tool
            ViewFinder = 1 - ViewFinder
            OriginX = 0
            OriginY = 0
          Case #PB_Shortcut_Prior                                              ; Prior        Change viewfinder color forward
           If ViewFinder = #TRUE
            If ViewFinderColor = #Black
              ViewFinderColor = #Red
            ElseIf ViewFinderColor = #Red
              ViewFinderColor = #Green
            ElseIf ViewFinderColor = #Green
              ViewFinderColor = #Blue
            ElseIf ViewFinderColor = #Blue
              ViewFinderColor = #Yellow
            ElseIf ViewFinderColor = #Yellow
              ViewFinderColor = #Cyan
            ElseIf ViewFinderColor = #Cyan
              ViewFinderColor = #Magenta
            ElseIf ViewFinderColor = #Magenta
              ViewFinderColor = #White
            ElseIf ViewFinderColor = #White
              ViewFinderColor = #Black
            EndIf
           EndIf
          Case #PB_Shortcut_Next                                               ; Next         Change viewfinder color backward
           If ViewFinder = #TRUE
            If ViewFinderColor = #Black
              ViewFinderColor = #White
            ElseIf ViewFinderColor = #Red
              ViewFinderColor = #Black
            ElseIf ViewFinderColor = #Green
              ViewFinderColor = #Red
            ElseIf ViewFinderColor = #Blue
              ViewFinderColor = #Green
            ElseIf ViewFinderColor = #Yellow
              ViewFinderColor = #Blue
            ElseIf ViewFinderColor = #Cyan
              ViewFinderColor = #Yellow
            ElseIf ViewFinderColor = #Magenta
              ViewFinderColor = #Cyan
            ElseIf ViewFinderColor = #White
              ViewFinderColor = #Magenta
            EndIf
           EndIf
          Case #PB_Shortcut_Insert                                             ; Insert       Change viewfinder cursor origin
            OriginX = CursorPosition\x
            OriginY = CursorPosition\y
          Case #PB_Shortcut_Left                                               ; Left         Move viewfinder cursor left
            SetCursorPos_(CursorPosition\x - MoveCursorStep, CursorPosition\y)
            ArrowKeyPressed = ArrowKeyPressed + 1
          Case #PB_Shortcut_Up                                                 ; Up           Move viewfinder cursor up
            SetCursorPos_(CursorPosition\x, CursorPosition\y - MoveCursorStep)
            ArrowKeyPressed = ArrowKeyPressed + 1
          Case #PB_Shortcut_Right                                              ; Right        Move viewfinder cursor right
            SetCursorPos_(CursorPosition\x + MoveCursorStep, CursorPosition\y)
            ArrowKeyPressed = ArrowKeyPressed + 1
          Case #PB_Shortcut_Down                                               ; Down         Move viewfinder cursor down
            SetCursorPos_(CursorPosition\x, CursorPosition\y + MoveCursorStep)
            ArrowKeyPressed = ArrowKeyPressed + 1
          Case #PB_Shortcut_Subtract                                           ; NumPad -     Factor smooth decrease
            If Factor < 0.005 ;sometimes you see strange effects if you go further...
              ;Nothing to do... 
            Else
              Factor = Factor * 0.98
              SourceWidth = Int(WindowWidth / Factor) >> 1 << 1 + 1
              SourceHeight = Int(WindowHeight / Factor) >> 1 << 1 + 1
            EndIf
          Case #PB_Shortcut_Add                                                ; NumPad +     Factor smooth increase
            Factor = Factor * 1.02
            SourceWidth = Int(WindowWidth / Factor) >> 1 << 1 + 1
            SourceHeight = Int(WindowHeight / Factor) >> 1 << 1 + 1
          Case #SF1                                                            ; Shift F1     Show / Hide watermark
            Copyright = 1 - Copyright
          Case #PB_Shortcut_Escape                                             ; Escape       Close program
            Quit = #TRUE
          Case #PB_Shortcut_E                                                  ; E            Direct source colors
            RasterOpCode = #SRCCOPY
          Case #PB_Shortcut_R                                                  ; R            Inverted source colors
            RasterOpCode = #NOTSRCCOPY
          Case #PB_Shortcut_S                                                  ; S            Halftone source colors
            ColorAdjustment = #HALFTONE
          Case #PB_Shortcut_D                                                  ; D            Illuminant_A source colors
            ColorAdjustment = #ILLUMINANT_A
          Case #PB_Shortcut_F                                                  ; F            Illuminant_B source colors
            ColorAdjustment = #ILLUMINANT_B
          Case #PB_Shortcut_G                                                  ; G            Illuminant_C source colors
            ColorAdjustment = #ILLUMINANT_C
          Case #PB_Shortcut_H                                                  ; H            Illuminant_D50 source colors
            ColorAdjustment = #ILLUMINANT_D50
          Case #PB_Shortcut_J                                                  ; J            Color_Adj_Min source colors
            ColorAdjustment = #COLOR_ADJ_MIN
          Case #PB_Shortcut_K                                                  ; K            Color_Adj_Max source colors
            ColorAdjustment = #COLOR_ADJ_MAX
          Case #PB_Shortcut_L                                                  ; L            Change language
            Select Language
              Case "DE"
                Language = "EN"
              Case "EN"
                Language = "FR"
              Case "FR"
                Language = "IT"
              Case "IT"
                Language = "PO"
              Case "PO"
                Language = "SP"
              Case "SP"
                Language = "Default"
              Case "Default"
                Language = "DE"
              Default
            EndSelect
            LoadHelp()
            If CaptureThreadID
                PauseThread(CaptureThreadID)
            EndIf
            StopDrawing()
            SetGadgetState(#Gadget_Image, DrawHelp())
            If CaptureThreadID
                ResumeThread(CaptureThreadID)
            EndIf
            StartDrawing(WindowOutput())
          Case #PB_Shortcut_C                                                  ; C            Show / hide pixel RGB color display
            ColorFinder = 1 - ColorFinder
          Case #PB_Shortcut_B                                                  ; B            Enable the capture to be saved to a file
            CopyBitMapToImage = #TRUE
          Default
        EndSelect
      Case #WM_LBUTTONDOWN
        ;
        ; Makes possible to drag the magnifier using left mouse button, but only for Main window (not for help)
        ;
        If WindowID() = hWndMain
            ReleaseCapture_()
            SendMessage_(hWndMain, #WM_NCLBUTTONDOWN, #HTCAPTION, 0)
        EndIf
      Default

    EndSelect

  Until Quit
  
  ;
  ; Disable all shortcuts
  ;
  RemoveKeyboardShortcut(#MagnifierWindowID, #PB_Shortcut_All)

  StopDrawing()
  KillThread(CaptureThreadID)
  CloseWindow(#MagnifierWindowID)
  TerminateProcess_(GetCurrentProcess_(), 0)
End