For OBS Studio-Filter-Carding

Share your advanced PureBasic knowledge/code with the community.
AZJIO
Addict
Addict
Posts: 2141
Joined: Sun May 14, 2017 1:48 am

For OBS Studio-Filter-Carding

Post by AZJIO »

I record videos in the "OBS Studio" program. To record a part of the screen, I need to add the "Cropping" filter and specify the padding from the sides of the screen. To simplify the task, I have made calculations.
I've added an adjustment for transparent areas at the edges, as shadows are considered as part of the window size.
Perhaps I need to calculate the client area and add the width and height of the window borders, depending on the window style.
Download yandex, upload.ee

Code: Select all

;- TOP
;- @AZJIO v1.0 (03.07.2025)

Define UserIntLang, *Lang
If OpenLibrary(0, "kernel32.dll")
	*Lang = GetFunction(0, "GetUserDefaultUILanguage")
	If *Lang
		UserIntLang = CallFunctionFast(*Lang)
	EndIf
	CloseLibrary(0)
EndIf

#CountStrLang = 9
Global Dim Lng.s(#CountStrLang)
Lng(1) = "Select a window"
Lng(2) = "Refresh list"
Lng(3) = "Left"
Lng(4) = "Top"
Lng(5) = "Right"
Lng(6) = "Bottom"
Lng(7) = "Visible windows ("
Lng(8) = "Delta"
Lng(9) = "Client region"

If UserIntLang = 1049 ; ru
	Lng(1) = "Выберите окно"
	Lng(2) = "Обновить список"
	Lng(3) = "Слева"
	Lng(4) = "Сверху"
	Lng(5) = "Справа"
	Lng(6) = "Снизу"
	Lng(7) = "Видимые окна ("
	Lng(8) = "Поправка"
	Lng(9) = "Клиентскую часть"
EndIf


;- # Constants
#Window = 0

;- ● Enumeration
Enumeration
	#Btn
	#LIG
	#txtL
	#txtT
	#txtR
	#txtB
	#txtD
	#FieldL
	#FieldT
	#FieldR
	#FieldB
	#FieldD
	#ch
EndEnumeration

;- ● Global
Global hIconProg.l
Global hIconFolder.l
Global WinRect.RECT


Procedure Limit(*Value.integer, Min, Max)
  If *Value\i < Min
    *Value\i = Min
  ElseIf *Value\i > Max
    *Value\i = Max
  EndIf
EndProcedure

Procedure EnumChildProc(hwnd.l, *hwnd)
	Protected Title${256}
	Protected class${256}
	Protected hIcon.l
	If IsWindowVisible_(hwnd)
		GetWindowText_(hwnd, @Title$, 256)
		
		If Asc(Title$)
			If Title$ = "Program Manager"
				ProcedureReturn 1
			EndIf
			hIcon = GetClassLongPtr_(hwnd, #GCL_HICON)
			If hIcon
				AddGadgetItem(#LIG, n, Title$, hIcon)
			Else
				GetClassName_(hwnd, @class$, 256)
				If class$ = "CabinetWClass"
					AddGadgetItem(#LIG, n, Title$, hIconFolder)
				Else
					AddGadgetItem(#LIG, n, Title$, hIconProg)
				EndIf
			EndIf
			SetGadgetItemData(#LIG, n, hwnd)
			n+1
		EndIf
	EndIf
    ProcedureReturn 1
EndProcedure

; Fred
; https://www.purebasic.fr/english/viewtopic.php?t=7424
Procedure SetForegroundWindow(hWnd)
    Protected foregroundThreadID, ourThreadID
    If GetWindowLong_(hWnd, #GWL_STYLE) & #WS_MINIMIZE
        ; ShowWindow_(hWnd, #SW_MAXIMIZE)
        ShowWindow_(hWnd, #SW_SHOWNOACTIVATE)
        UpdateWindow_(hWnd)
    EndIf
    foregroundThreadID = GetWindowThreadProcessId_(GetForegroundWindow_(), 0)
    ourThreadID = GetCurrentThreadId_()

    If (foregroundThreadID <> ourThreadID)
        AttachThreadInput_(foregroundThreadID, ourThreadID, #True);
    EndIf

    SetForegroundWindow_(hWnd)

    If (foregroundThreadID <> ourThreadID)
        AttachThreadInput_(foregroundThreadID, ourThreadID, #False)
    EndIf

    InvalidateRect_(hWnd, #Null, #True)
EndProcedure

Procedure SizeWindowHandler()
	w = WindowWidth(#Window)
	h = WindowHeight(#Window)
	ResizeGadget(#LIG, #PB_Ignore, #PB_Ignore, w - 174, h - 20)
	#PosX = 154
    ResizeGadget(#Btn, w - #PosX, #PB_Ignore, #PB_Ignore, #PB_Ignore)
    ResizeGadget(#txtL, w - #PosX, #PB_Ignore, #PB_Ignore, #PB_Ignore)
    ResizeGadget(#txtT, w - #PosX, #PB_Ignore, #PB_Ignore, #PB_Ignore)
    ResizeGadget(#txtR, w - #PosX, #PB_Ignore, #PB_Ignore, #PB_Ignore)
    ResizeGadget(#txtB, w - #PosX, #PB_Ignore, #PB_Ignore, #PB_Ignore)
    ResizeGadget(#ch, w - #PosX, #PB_Ignore, #PB_Ignore, #PB_Ignore)
	#PosX2 = 94
    ResizeGadget(#FieldL, w - #PosX2, #PB_Ignore, #PB_Ignore, #PB_Ignore)
    ResizeGadget(#FieldT, w - #PosX2, #PB_Ignore, #PB_Ignore, #PB_Ignore)
    ResizeGadget(#FieldR, w - #PosX2, #PB_Ignore, #PB_Ignore, #PB_Ignore)
    ResizeGadget(#FieldB, w - #PosX2, #PB_Ignore, #PB_Ignore, #PB_Ignore)
EndProcedure


Define hwnd.l, res$, n, w, h, delta
Define left, right, top, bottom

ExtractIconEx_("Shell32.dll", 3, 0, @hIconFolder, 1)
ExtractIconEx_("Shell32.dll", 2, 0, @hIconProg, 1)


;-┌──GUI──┐
If OpenWindow(#Window, 0, 0, 724, 560, Lng(1),
              #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_SizeGadget | #PB_Window_MaximizeGadget | #PB_Window_MinimizeGadget)
	ButtonGadget(#Btn, 570, 10, 144, 30, Lng(2))
	TextGadget(#txtL, 570 , 50, 60, 25, Lng(3))
	TextGadget(#txtT, 570 , 80, 60, 25, Lng(4))
	TextGadget(#txtR, 570 , 110, 60, 25, Lng(5))
	TextGadget(#txtB, 570 , 140, 60, 25, Lng(6))
	TextGadget(#txtD, 570 , 170, 70, 25, Lng(8))
	
	StringGadget(#FieldL, 630 , 50, 70, 25, "")
	StringGadget(#FieldT, 630 , 80, 70, 25, "")
	StringGadget(#FieldR, 630 , 110, 70, 25, "")
	StringGadget(#FieldB, 630 , 140, 70, 25, "")
	StringGadget(#FieldD, 640 , 170, 70, 25, "8")
	
	CheckBoxGadget(#ch, 570 , 210, 140, 25, Lng(9))
	
	ListIconGadget(#LIG, 10, 10, 550, 540, "", 500)
	EnumWindows_(@EnumChildProc(), @hwnd)
	SetGadgetItemAttribute(#LIG, 2, #PB_ListIcon_ColumnWidth , #LVSCW_AUTOSIZE, 0)
	SetGadgetItemText(#LIG, -1, Lng(7) + Str(CountGadgetItems(#LIG)) + ")")
	
	BindEvent(#PB_Event_SizeWindow, @SizeWindowHandler())
	
;-┌──Loop──┐
	Repeat
		Select WaitWindowEvent()
			Case #PB_Event_Gadget
				Select EventGadget()
					Case #Btn
						ClearGadgetItems(#LIG)
						n = 0
						hwnd = 0
						EnumWindows_(@EnumChildProc(), @hwnd)
						SetGadgetItemAttribute(#LIG, 2, #PB_ListIcon_ColumnWidth , #LVSCW_AUTOSIZE, 0)
						SetGadgetItemText(#LIG, -1, Lng(7) + Str(CountGadgetItems(#LIG)) + ")")
					Case #LIG
						If EventType()  = #PB_EventType_LeftClick
							n = GetGadgetState(#LIG)
							If n > -1
								delta = 0
								hwnd = GetGadgetItemData(#LIG, n)
								If IsIconic_(hwnd)
									SetForegroundWindow(hwnd)
								EndIf
								ExamineDesktops()
								w = DesktopWidth(0)
								h = DesktopHeight(0)
								If GetGadgetState(#ch) & #PB_Checkbox_Checked
									GetClientRect_(hwnd, @WinRect)
									ClientToScreen_(hwnd, @WinRect)
									With WinRect
										\right + \left
										\bottom + \top
									EndWith
								Else
									GetWindowRect_(hwnd, @WinRect)
									delta = Val(GetGadgetText(#FieldD))
								EndIf
								With WinRect
									left = \left + delta
									right = w - \right + delta
									top = \top
									bottom = h - \bottom + delta
									Limit(@left, 0, w)
									Limit(@right, 0, w)
									Limit(@top, 0, h)
									Limit(@bottom, 0, h)
									SetGadgetText(#FieldL, Str(left))
									SetGadgetText(#FieldT, Str(top))
									SetGadgetText(#FieldR, Str(right))
									SetGadgetText(#FieldB, Str(bottom))
								EndWith
							EndIf
						EndIf
				EndSelect
			Case #PB_Event_CloseWindow
				CloseWindow(#Window)
				DestroyIcon_(hIconProg)
				DestroyIcon_(hIconFolder)
				End
		EndSelect
	ForEver
EndIf