Code: Select all
;
;
; ------------------------------------------------------------------
;
; PureBasic example code showing how to use; the clipboard viewer
; chain, calculate a CRC32 checksum of an image in the clipboard,
; detecting clipboard changes through window callback events,
; capturing owner and non-owner windows and saving the capture
; to clipboard.
;
; Press key "1" to capture window and CRC32 checksum
; Press key "2" to compare saved checksum with current clipboard
;
; By Teddy Rogers / PureBasic 5.22 LTS
;
; ------------------------------------------------------------------
;
; Declare the PrintWindow function from User32.dll
Prototype.i PrintWindow(hWnd, hdc, flag)
Global PrintWindow.PrintWindow
; Declare our procedures here...
Declare Snapshot()
Declare ClipboardChecksum()
Declare WindowCallback(WindowID.i, uMsg.l, wParam.l, lParam.l)
; This flag is used to prevent two drawing operations running at the same time after #WM_DRAWCLIPBOARD message is received from the callback...
; ...and we StartDrawing again to calculate the CRC32 checksum.
Global DrawingFinished = #False
; Save our CRC32 checksum values...
Global CRC32_1
Global CRC32_2
; Path and filename if you want to check what image(s) was drawn (enable disabled SaveImage code below)
Global FileName.s = "E:\Clipboard.bmp"
; Start the main window event...
If OpenWindow(0, 0, 0, 200, 150, "Window", #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_ScreenCentered)
; Added ourselves to the clipboard viewer chain using the SetClipboardViewer function...
; ...then start the window callback to start receiving window events.
MsgChain = SetClipboardViewer_(WindowID(0))
SetWindowCallback(@WindowCallback(), 0)
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
; Politley remove ourselves from the chain of clipboard viewers by letting the next window know we are closing...
; ...and pass on the hWnd of the window in our message chain.
ChangeClipboardChain_(WindowID(0), MsgChain)
End
EndSelect
; Once our window is available we can capture the window and save it to the clipboard by pressing key 1...
; ...after it has been captured we can then calculate the CRC32 checksum of the image in the clipboard.
If GetAsyncKeyState_(#VK_1) & $8000 ; Key Press "1"
MessageBeep_(#MB_ICONINFORMATION) ; Sound a simple windows beep to notify that we captured a window
CRC32_1 = Snapshot()
If CRC32_1
Debug "Window CRC32_1 checksum calculated!"
EndIf
EndIf
; Press "2" key to calculate the CRC32 checksum of the image currently in the clipboard and compare it against our first checksum...
If (GetAsyncKeyState_(#VK_2) & $8000) ; Key Press "2"
MessageBeep_(#MB_ICONINFORMATION) ; Sound a simple windows beep to notify that we captured a window
CRC32_2 = ClipboardChecksum()
If CRC32_2
If CRC32_1 = CRC32_2
Debug "The clipboard contents match!"
Else
Debug "The clipboard contents do not match!"
EndIf
Debug "CRC32_1 = " + Hex(CRC32_1)
Debug "CRC32_2 = " + Hex(CRC32_2)
Else
Debug "Nothing to compare, clipboard empty or contains text?!"
EndIf
EndIf
ForEver
EndIf
; Capture our window using the PrintWindow function from User32.dll and save it to the clipboard
Procedure Snapshot()
Protected Checksum
If OpenLibrary(User32, "User32.dll")
PrintWindow = GetFunction(User32, "PrintWindow")
hWnd = WindowID(0)
;hWnd = FindWindow_(0,"Window") ; Enable this and change the window title if you want to capture another window
DrawingFinished = #False
If hWnd
If GetWindowRect_(hWnd, r.RECT) ; Get the window dimensions
If CreateImage(CapImage, r\right-r\left, r\bottom-r\top) ; Create an empty image to draw on and calculate the window size
hdc = StartDrawing(ImageOutput(CapImage))
; Call the PrintWindow function to capture the window contents and save it to the clipboard
If PrintWindow(hWnd, hdc, CapImage) ; Use PrintWindow function to capture the window image to "CapImage"
SetClipboardImage(CapImage) ; Save the new contents to the clipboard
; Calculate the length of the checksum from the image size
Checksum = CRC32Fingerprint((DrawingBuffer()), ((DrawingBufferPitch()) * ImageHeight(CapImage)))
EndIf
StopDrawing()
;SaveImage(CapImage, FileName.s) ; Enable this if you want to see the image
FreeImage(CapImage) ; Remember to free up the memory when done!
DeleteDC_(hdc) ; Delete any used device context
EndIf
EndIf
EndIf
DrawingFinished = #True
CloseLibrary(User32)
EndIf
ProcedureReturn Checksum
EndProcedure
; Calculate the CRC32 checksum of the data (IMAGE) in the clipboard.
; Other types clipboard contents such as text will naturally return #Null in "Checksum"
Procedure ClipboardChecksum()
Protected Checksum
; Quick delay to give time for clipboard contents to be updated...
; ...if you remove this sometimes the clipboard will be empty after being called from the window callback and CRC32 will return #Null
Delay(5)
Clipboard = GetClipboardImage(#PB_Any) ; Get the current clipboard contents
; If the clipboard contents are all good StartDrawing to "Clipboard". We need to start drawing only because...
; ...we need to know where in memory the contents are to calculate the CRC32 checksum. We find this by calling DrawingBuffer function
If Clipboard
If StartDrawing(ImageOutput(Clipboard))
Checksum = CRC32Fingerprint((DrawingBuffer()), ((DrawingBufferPitch()) * ImageHeight(Clipboard))) ; Calculate the length of the checksum from the image size
StopDrawing()
;SaveImage(Clipboard, FileName.s) ; Enable this if you want to see the image
FreeImage(Clipboard) ; Remember to free up the memory when done!
EndIf
EndIf
ProcedureReturn Checksum
EndProcedure
; WindowCallback procedure to listen for our chosen window events...
Procedure WindowCallback(WindowID.i, uMsg.l, wParam.l, lParam.l)
Select uMsg
; Only clipboard viewer windows receive this message. These are windows that have been added to the clipboard viewer chain by using the SetClipboardViewer function.
; Each window that receives the WM_DRAWCLIPBOARD message must call the SendMessage function to pass the message on to the next window in the clipboard viewer chain.
Case #WM_DRAWCLIPBOARD
Debug "Clipboard updated..."
SendMessage_(MsgChain, uMsg.l, wParam.l, lParam.l) ; Pass the message on to the next window to let them know the clipboard has been updated.
If DrawingFinished = #True ; If there are no other drawing operations going on calculate the CRC32 checksum.
CRC32_2 = ClipboardChecksum()
If CRC32_1
If CRC32_1 = CRC32_2
Debug "The clipboard contents match!"
Else
Debug "The clipboard contents do not match!"
EndIf
Debug "CRC32_1 = " + Hex(CRC32_1)
Debug "CRC32_2 = " + Hex(CRC32_2)
Else
Debug "Nothing To compare, clipboard empty or contains text?!"
EndIf
EndIf
; Sent to the first window in the clipboard viewer chain when a window is being removed from the chain.
; When a clipboard viewer window receives the WM_CHANGECBCHAIN message, it should call the SendMessage function to pass the message to the next window in the chain.
Case #WM_CHANGECBCHAIN
If wParam = MsgChain
MsgChain = lParam
Else
SendMessage_(MsgChain, uMsg.l, wParam.l, lParam.l)
EndIf
EndSelect
ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure
Ted.