Gadget auf Realgröße skalieren.. Aber wie

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
PureUser1966
Beiträge: 29
Registriert: 02.02.2017 21:03
Wohnort: Cologne / Germany

Gadget auf Realgröße skalieren.. Aber wie

Beitrag von PureUser1966 »

Eine Frage an die Profi's hier:

Ich möchte ein beliebiges (hier im Beispiel ein Canvasgadget) auf eine reale Größe skalieren.
Soll heißen wenn ich ein Lineal auf den Bildschirm lege soll das Gadget die Maße haben die ich angebe (in mm).

Im Beispiel unten soll das Gadget 170 mm breit und 200 mm hoch sein.
Ich rechne also zB die Breite in Inches um und multipliziere das dann mit dem Ergebnis aus GetDeviceCaps_(lhDC, #LOGPIXELSX).
Das dabei erzielte Ergebnis ergibt immer ein zu großes Gadget beim nachmessen mit dem Lineal auf dem Screen.

Beim rumprobieren mit verschieden Werten anstelle des GetDeviceCaps_(lhDC, #LOGPIXELSX) hab ich herausgefunden das der Wert 82
immer korrekte Werte liefert. Das ist zwar schön und würde mein Problem lösen, ich würde aber gerne wissen warum das so ist,
bzw. warum GetDeviceCaps_(lhDC, #LOGPIXELSX) nicht funktioniert bzw. ein falsches Ergenis liefert.

Oder anders gesagt, wo ist mein Denkfehler?
Ich code noch nicht so lange mit PB, also vergebt mir meine Unwissenheit ..

LG, Stefan

Code: Alles auswählen


; ---------------------------------------
; project
;	name:		gadget screen size test
; 	date:		31.01.2017
;   author:		S.D.A.
;	lang:		PB (5.51 Windows X64) 
;					tested
;	purpose: 	na
; ---------------------------------------
	
EnableExplicit								; the magic one

; different window id's
Enumeration 0 Step 1
	#MAIN_WINDOWID							; window ID of test screen
EndEnumeration

; different gadget id's
Enumeration 0 Step 1
	#GAD_CANVAS_01	
EndEnumeration	


; vars
	Define.i	iEvent	=	0						; WindowEvent
	Define.i	iQuit	=	0						; 1== Quits the event loop and terminates program
	Define.i	iCurX, iCurY, iGad, iGadFlags		; gadget init stuff
	Define.i	iWidth, iHeight						; gadget init stuff
	Define.l	lhDC								; -> 
	Define.s	sMsg	=	""						; teststring
	
	
; const	
	#INCH_MM	= 25.40								; 1 inch = 25.4 mm
	
	
	
	; -------------------------------------------------------------------------------	
	sMsg = "PureBasic Gadget size Test Window"
	If OpenWindow(0, 100, 200, 195, 260, sMsg, #PB_Window_SystemMenu | #PB_Window_Maximize)
		
		lhDC = GetDC_(#Null)														; retrieves device context for the entire screen
		
		; create gadget(s)
		iCurX = 	100
		iCurY = 	50
		iWidth = 	(170.00 / #INCH_MM) * GetDeviceCaps_(lhDC, #LOGPIXELSX)			; zu groß (ergebnis von GetDeviceCaps_(lhDC, #LOGPIXELSX) = 96
		iWidth = 	(170.00 / #INCH_MM) * 82										; dieser Wert funktioniert, ABER WARUM ??
		
		iHeight = 	(200.00 / #INCH_MM) * GetDeviceCaps_(lhDC, #LOGPIXELSY)			; zu groß (ergebnis von GetDeviceCaps_(lhDC, #LOGPIXELSY) = 96
		iHeight = 	(200.00 / #INCH_MM) * 82										; dieser Wert funktioniert, ABER WARUM ??
		
		iGad = 		#GAD_CANVAS_01
		iGadFlags = #Null
		CanvasGadget(iGad, iCurX, iCurY, iWidth,iHeight, iGadFlags)
		
		Repeat
			iEvent = WaitWindowEvent()
			If iEvent = #PB_Event_CloseWindow
				iQuit = 1
			EndIf
		Until iQuit = 1
	EndIf



	End   																			; All the opened windows are closed automatically by PureBasic

move.w #$7fff, $dff09a
ILLEGAL
Benutzeravatar
helpy
Beiträge: 636
Registriert: 29.08.2004 13:29

Re: Gadget auf Realgröße skalieren.. Aber wie

Beitrag von helpy »

GetDeviceCaps gibt nicht die Auflösung des Monitors zurück, sondern die Einstellung von Windows.

Schau in der Windows-Systemsteuerung unter Anzeige nach.
Dort gibt es die Einstellung für die "Lesbarkeit auf dem Bildschirm".
Wenn dort 100% eingestellt ist, dann gibt GetDeviceCaps 96dpi zurück!
... bei 125% sind es 120dpi
... bie 150% sind es 144dpi


Informiere Dich über die API-Funktion "GetDpiForMonitor" ...

Minimum-Anforderung für diese Funktion:

==> Windows 8.1 [desktop apps only]
==> oder Windows Server 2012 R2 [desktop apps only]


Beispiel von Danilo: http://www.purebasic.fr/english/viewtop ... 83#p463883
Windows 10
PB Last Final / (Sometimes testing Beta versions)
Benutzeravatar
PureUser1966
Beiträge: 29
Registriert: 02.02.2017 21:03
Wohnort: Cologne / Germany

Re: Gadget auf Realgröße skalieren.. Aber wie

Beitrag von PureUser1966 »

Danke für die Antwort, dann ist das dann doch nicht so trivial.
Werde mich heute Nachmittag mal daran versuchen.

LG, Stefan
move.w #$7fff, $dff09a
ILLEGAL
Benutzeravatar
juergenkulow
Beiträge: 188
Registriert: 22.12.2016 12:49
Wohnort: :D_üsseldorf-Wersten

Re: Gadget auf Realgröße skalieren.. Aber wie

Beitrag von juergenkulow »

Hallo PureUser1966,

leider liefert GetDeviceCaps fragwürdige, ungenaue Ergebnisse. Habe folgende Werte gemessen:

Bildschirm ausgegeben Größe Dpi von GetDeviceCaps
Dell 175x205 mm allerdings bei 96 dpi
Sony 164x194 mm " " 96 dpi
Wacom 147x174 mm " " 192 dpi

Die Idee der ganauen Ausgabe auf jede Bildschirmgröße finde ich toll.


Hallo PB-Universum,

leider habe ich kein Beispiel zur richtigen Verwendung von Shcore.dll GetDpiForMonitor in PureBasic gefunden.
Hier ist mein Versuch mit einigen offenen Fragen:

Code: Alles auswählen

; Warum: Male mm_Gitter 170.0 x 100.0 mm - Die Bildschirmgrößen in mm müssen wahrscheinlich geändert werden mit Massband oder Specs.
; Erstellt mit PureBasic  5.51 (x64) auf Wacom Cintiq Companion 2 2560x1440xR8G8B8A8@59 Windows 8.1 64 bit 
; Nach einem Neustart gab das Programm den halben dpiX und dpiY Wert aus 111 statt 221.
; Aktuell werden in der IDE die richtigen dpiX, dpiY Werte ausgeben aber nicht in der EXE und
;   der InputRequester ist in der IDE zu klein und in der EXE in Ordnung und
;   Warum ist in der EXE plötzlich der Monitor Rect, Workarea Rect 0,0,1280,720 bei einem 2560x1440?
; offen Umgang mit mehreren Bildschirmen 
;   Testen, anpassen unter Linuxe-
;   Testen, anpassen unter MacOS.
;   Einmaliges eingeben bei Installation, Umgebungsänderung, Einstellungsänderung und Speicherung mit Preference, INI und, oder Registry.
;   Procedure.f Pixel_X_zu_Millimeter(Pixel.w)
;   Procedure.f Pixel_Y_zu_Millimeter(Pixel.w)
; erl.  GetMonitorInfo_(hMonitor,@mi)   ; ? Gibt es doch schon seit Windows NT, wieso #Bs_Win81Plus
; erl.  die Gitterausgabe ist in der IDE in Ordnung aber in der EXE 200% gezoomt bzw. schlecht. 

EnableExplicit
Define BildschirmBreite_mm.f=294.0 
Define BildschirmHoehe_mm.f =166.0 
Declare Male_mm_Gitter(PixelX.w,PixelY.w, Gitter_x_mm.f, Gitter_y_mm.f ,BildschirmBreite_mm.f,BildschirmHoehe_mm.f,Array Farben.d(1)) 
Declare.w Millimeter_zu_Pixel_X(mm.f) 
Declare.w Millimeter_zu_Pixel_Y(mm.f)
#Bs_Win81Plus=#True
Global dpiX.l=0, dpiY.l=0 , unten.l=0, rechts.l=0 
CompilerIf #PB_Compiler_OS=#PB_OS_Windows 
  CompilerIf #Bs_Win81Plus
    Prototype protoGetDpiForMonitor(hmonitor, dpiType.l, *dpiX.Long, *dpiY.Long) ; Warum sind dpiX und dpiY nicht float? 
    Global GetDpiForMonitor.protoGetDpiForMonitor
    If OSVersion()>=#PB_OS_Windows_8_1
      Define libShcore = OpenLibrary(#PB_Any, "Shcore.dll")
      If libShcore
        GetDpiForMonitor = GetFunction(libShcore,"GetDpiForMonitor") ; Win8.1+
      EndIf
    EndIf 
  CompilerEndIf
  Declare MonitorEnumProc(hMonitor, hdcMonitor, *lprcMonitor.RECT, dwData.l)
  EnumDisplayMonitors_(0,0,@MonitorEnumProc(),0)
CompilerEndIf  
InitSprite()
ExamineDesktops()
InitKeyboard() 
Dim GitterFarben.d(5)
GitterFarben(0)=RGB($00,$00,$00)  ; Hintergrund
GitterFarben(1)=RGB($18,$28,$00)  ; Farbe 1 mm 
GitterFarben(2)=RGB($1C,$38,$00)  ; Farbe 5 mm
GitterFarben(3)=RGB($24,$48,$00)  ; Farbe 10 mm
GitterFarben(4)=RGB($2C,$58,$00)  ; Farbe 50 mm 
If dpiX>0 : BildschirmBreite_mm= 25.4/dpiX * DesktopWidth(0) :EndIf
If dpiY>0 : BildschirmHoehe_mm = 25.4/dpiY * DesktopHeight(0):EndIf
Define DesktopWidth_Pixel =DesktopWidth(0) 
Define DesktopHeight_Pixel=DesktopHeight(0) 
If rechts>0 : Define FaktorX.f=DesktopWidth(0)/rechts: Else : FaktorX=1.0 :EndIf
If unten >0 : Define FaktorY.f=DesktopHeight(0)/unten: Else : FaktorY=1.0 :EndIf 
CompilerIf #Bs_Win81Plus
  BildschirmBreite_mm=ValF(InputRequester("dpiX:"+Str(dpiX)+" "+Str(rechts),
                                          "Breite des Bildschirms in mm:",
                                          StrF(BildschirmBreite_mm/FaktorX,1)))*FaktorX
  BildschirmHoehe_mm =ValF(InputRequester("dpiY:"+Str(dpiY)+" "+Str(unten) ,
                                          "Höhe des Bildschirms in mm:"  ,
                                          StrF(BildschirmHoehe_mm/FaktorY,1)))*FaktorY
CompilerElse
  BildschirmBreite_mm=ValF(InputRequester("dpiX:"+Str(dpiX)+" "+Str(rechts),
                                          "Breite des Bildschirms in mm:",
                                          StrF(BildschirmBreite_mm,1)))*FaktorX
  BildschirmHoehe_mm =ValF(InputRequester("dpiY:"+Str(dpiY)+" "+Str(unten) ,
                                          "Höhe des Bildschirms in mm:"  ,
                                          StrF(BildschirmHoehe_mm,1)))*FaktorY
CompilerEndIf  
Male_mm_Gitter(DesktopWidth(0),             ; Breite des Bildschirms in Pixel
               DesktopHeight(0),            ; Höhe   des Blldschirms in Pixel 
               170.0,                       ; Gitter Brreite in mm 
               100.0,                       ; Gitter Höhe    in mm
               BildschirmBreite_mm,         ; Breite des Bildschirms in mm
               BildschirmHoehe_mm,          ; Höhe   des Blldschirms in mm 
               GitterFarben())              ; Farben des Gitters 
Repeat : Define Event = WaitWindowEvent() :  Until Event = #PB_Event_CloseWindow ; Hauptschleife Alt-F4 Taste beendet Programm 
End 

CompilerIf #PB_Compiler_OS=#PB_OS_Windows
  Structure MONITORINFOEX_ Align #PB_Structure_AlignC :  cbSize.l : rcMonitor.RECT : rcWork.RECT : dwFlags.l : szDevice.c[#CCHDEVICENAME] :EndStructure
  Procedure MonitorEnumProc(hMonitor, hdcMonitor, *lprcMonitor.RECT, dwData.l)
    Shared dpiX, dpiY, rechts, unten
    Protected mi.MONITORINFOEX_
    mi\cbSize = SizeOf( MONITORINFOEX_ )
    GetMonitorInfo_(hMonitor,@mi)
    rechts = mi\rcMonitor\right  - mi\rcMonitor\left
    unten  = mi\rcMonitor\bottom - mi\rcMonitor\top
    CompilerIf #Bs_Win81Plus
      #MDT_RAW_DPI        = 2
      If OSVersion()>=#PB_OS_Windows_8_1
        If GetDpiForMonitor
          GetDpiForMonitor(hmonitor, #MDT_RAW_DPI, @dpiX, @dpiY)
        EndIf
      EndIf 
    CompilerEndIf
    ProcedureReturn #True
  EndProcedure
CompilerEndIf

Procedure.w Millimeter_zu_Pixel_X(mm.f) 
  Shared Bildschirmbreite_mm, DesktopWidth_Pixel
  ProcedureReturn  mm*DesktopWidth_Pixel/Bildschirmbreite_mm
EndProcedure

Procedure.w Millimeter_zu_Pixel_Y(mm.f)
  Shared Bildschirmhoehe_mm, DesktopHeight_Pixel
  ProcedureReturn mm*DesktopHeight_Pixel/Bildschirmhoehe_mm
EndProcedure  

Procedure Male_mm_Gitter(PixelX.w,PixelY.w, Gitter_x_mm.f, Gitter_y_mm.f ,BildschirmBreite_mm.f,BildschirmHoehe_mm.f,Array Farben.d(1)) 
  Define Bildnr.l =CreateImage(#PB_Any, PixelX, PixelY,32,Farben(0))
  Define xoffset.f=PixelX/BildschirmBreite_mm
  Define yoffset.f=PixelY/BildschirmHoehe_mm
  Define x.f 
  Define y.f 
  
  StartDrawing(ImageOutput(Bildnr))
  x=1.0 : While x<=Gitter_x_mm : LineXY(Int(x*xoffset),0,Int(x*xoffset),Gitter_y_mm*yoffset,Farben(1)): x+5.0  : Wend  ; 1mm  
  x=2.0 : While x<=Gitter_x_mm : LineXY(Int(x*xoffset),0,Int(x*xoffset),Gitter_y_mm*yoffset,Farben(1)): x+5.0  : Wend   
  x=3.0 : While x<=Gitter_x_mm : LineXY(Int(x*xoffset),0,Int(x*xoffset),Gitter_y_mm*yoffset,Farben(1)): x+5.0  : Wend   
  x=4.0 : While x<=Gitter_x_mm : LineXY(Int(x*xoffset),0,Int(x*xoffset),Gitter_y_mm*yoffset,Farben(1)): x+5.0  : Wend 
  y=1.0 : While y<=Gitter_y_mm : LineXY(0,Int(y*yoffset),Gitter_x_mm*xoffset,Int(y*yoffset),Farben(1)): y+5.0  : Wend 
  y=2.0 : While y<=Gitter_y_mm : LineXY(0,Int(y*yoffset),Gitter_x_mm*xoffset,Int(y*yoffset),Farben(1)): y+5.0  : Wend 
  y=3.0 : While y<=Gitter_y_mm : LineXY(0,Int(y*yoffset),Gitter_x_mm*xoffset,Int(y*yoffset),Farben(1)): y+5.0  : Wend 
  y=4.0 : While y<=Gitter_y_mm : LineXY(0,Int(y*yoffset),Gitter_x_mm*xoffset,Int(y*yoffset),Farben(1)): y+5.0  : Wend 
  x=5.0 : While x<=Gitter_x_mm : LineXY(Int(x*xoffset),0,Int(x*xoffset),Gitter_y_mm*yoffset,Farben(2)): x+10.0 : Wend ; 5 mm 
  y=5.0 : While y<=Gitter_y_mm : LineXY(0,Int(y*yoffset),Gitter_x_mm*xoffset,Int(y*yoffset),Farben(2)): y+10.0 : Wend 
  x=0.0 : While x<=Gitter_x_mm : LineXY(Int(x*xoffset),0,Int(x*xoffset),Gitter_y_mm*yoffset,Farben(3)): x+10.0 : Wend ; 10 mm 
  y=0.0 : While y<=Gitter_y_mm : LineXY(0,Int(y*yoffset),Gitter_x_mm*xoffset,Int(y*yoffset),Farben(3)): y+10.0 : Wend 
  x=0.0 : While x<=Gitter_x_mm : LineXY(Int(x*xoffset),0,Int(x*xoffset),Gitter_y_mm*yoffset,Farben(4)): x+50.0 : Wend ; 50 mm 
  y=0.0 : While y<=Gitter_y_mm : LineXY(0,Int(y*yoffset),Gitter_x_mm*xoffset,Int(y*yoffset),Farben(4)): y+50.0 : Wend   
  StopDrawing()
  Define Fenster=OpenWindow(#PB_Any, 0, 0, PixelX, PixelY, "mm Gitter",   #PB_Window_BorderLess) 
  Define Gadget=CanvasGadget(#PB_Any, Millimeter_zu_Pixel_X( 10.0), Millimeter_zu_Pixel_Y( 10.0), 
                             Millimeter_zu_Pixel_X(170.0), Millimeter_zu_Pixel_Y(100.0))
  StartDrawing(CanvasOutput(Gadget))
  DrawImage(ImageID(Bildnr),0,0,PixelX,PixelY)
  StopDrawing()
EndProcedure
Bitte stelle Deine Fragen, denn den Erkenntnisapparat einschalten entscheidet über das einzig bekannte Leben im Universum.

Jürgen Kulow Wersten :D_üsseldorf NRW D Europa Erde Sonnensystem Lokale_Flocke Lokale_Blase Orion-Arm
Milchstraße Lokale_Gruppe Virgo-Superhaufen Laniakea Sichtbares_Universum
Antworten