Screen dimensions

Discussions related to mouse, keyboard, fonts and Graphical User Interface
KenDown
Posts: 327
Joined: Wed 04 Apr 2018, 06:36

Screen dimensions

Post by KenDown »

Does anyone know how to read screen dimensions in BBC BASIC, please? There is a routine provided somewhere (Help?) which successfully read the current screen, but if you have two screens of different sizes, how can you find the dimensions of the second?

I have a laptop running at 1400x800 and it is linked to a monitor 1920x1080, set up as extended monitor with the larger one being the main display. I would like to read the size of the laptop screen so that my program can create the appropriate window, bearing in mind that I have another laptop 1366x768 and a very old on 1280x840.

Thanks.
Zaphod
Posts: 78
Joined: Sat 23 Jun 2018, 15:51

Re: Screen dimensions

Post by Zaphod »

I have not done this but this link might help.
https://stackoverflow.com/questions/310 ... nd-monitor

Z
DDRM

Re: Screen dimensions

Post by DDRM »

Hi Kendall,

Not sure if this helps, but I think the piece you are remembering is under "using the entire screen" in the manual. The relevant commands are
SYS "GetSystemMetrics", 0 TO xscreen%
SYS "GetSystemMetrics", 1 TO yscreen%
which will give you the horizontal and vertical dimensions (in pixels) of the PRIMARY display - in this case presumably the big one.

Is the idea to set up a second window on the laptop screen? There's an MSDN page that might help:
https://docs.microsoft.com/en-us/window ... t-displays
It looks like you would need to set up a second device context for it, and then get the characteristics of that.

Hope that helps...

D
KenDown
Posts: 327
Joined: Wed 04 Apr 2018, 06:36

Re: Screen dimensions

Post by KenDown »

Yes, those are the calls I am using to find the size of the primary screen. It's the second (and smaller) screen whose size I need to read.

I don't really understand what you mean by "set up a second device context" but I'll look up the URL you give and see if that enlightens me.

Sorry to be a bear of such very little brain.
KenDown
Posts: 327
Joined: Wed 04 Apr 2018, 06:36

Re: Screen dimensions

Post by KenDown »

Hmmmm. No, it doesn't help. I tried following the instructions and ended up with this:

DIMcb%4
DIMdevicename%32
DIMdevicestring%128
DIMstateflags%4
DIMdeviceid%128
DIMdevicekey%128
DIMdisplaydeviceA{cb%,devicename%,devicestring%,stateflags%,deviceid%,devicekey%}
!cb%=4+32+128+4+128+128

FORi%=0TO2
SYS"EnumDisplayDevicesA",0,i%,displaydeviceA{},1TOsuccess%

PRINTsuccess%
PRINTdisplaydeviceA.devicename%
PRINTdisplaydeviceA.devicestring%
PRINTdisplaydeviceA.deviceid%
PRINTdisplaydeviceA.stateflags%
PRINT
NEXT
END

I have two monitors and the success% flag duly returns 1 when I call EnumDisplayDevicesA with 0 or 1 and returns 0 when I call with 2, so something is working, but the other values printed out below are the same - 0 in every case. Any advice is appreciated.
p_m21987
Posts: 177
Joined: Mon 02 Apr 2018, 21:51

Re: Screen dimensions

Post by p_m21987 »

You should put code in tags when you post it on the forum.

Code: Select all

Like this
DDRM

Re: Screen dimensions

Post by DDRM »

Hi Kendall,

Does this get you any further? I've modified your code a bit: notably
1) to put the value for cb% in the relevant structure element
2) To get the device name to print as an indirected string
3) For some reason the FOR i%...loop was throwing a "no such variable" error on the second monitor, so I have taken it out and hard-coded it.

Code: Select all

      DIMcb%4
      DIMdevicename%32
      DIMdevicestring%128
      DIMstateflags%4
      DIMdeviceid%128
      DIMdevicekey%128
      DIMdisplaydeviceA{cb%,devicename%,devicestring%,stateflags%,deviceid%,devicekey%}
      displaydeviceA.cb%=4+32+128+4+128+128

      SYS"EnumDisplayDevicesA",0,0,displaydeviceA{},1 TO success%

      PRINTsuccess%
      PRINT$$^displaydeviceA.devicename%
      PRINT $$^displaydeviceA.devicestring%
      PRINTdisplaydeviceA.deviceid%
      PRINTdisplaydeviceA.stateflags%
      PRINT

      SYS"EnumDisplayDevicesA",0,1,displaydeviceA{},1 TO success%

      PRINTsuccess%
      PRINT$$^displaydeviceA.devicename%
      PRINT $$^displaydeviceA.devicestring%
      PRINTdisplaydeviceA.deviceid%
      PRINTdisplaydeviceA.stateflags%
      PRINT

      END
With those changes I get different results from the two runs (encouragingly, the devicestrings read "DISPLAY1" and "DISPLAY2").

However, I'm not sure it gets you any closer to the info you need.

It looks like you might be able to do it using GetMonitorInfoA, but to do that you need to the handle of the monitor. You might be able to get that from MonitorFromWindow, if you put an output window (at least mostly) on the relevant monitor - is that possible? for example, if your accessory monitor is mapped to the left of the primary monitor, moving the BASIC window to a negative x coordinate with SetWindowPos?

Don't have time to play with this now, but if you can't get it to work, spell out how the monitors are arranged, and I'll have another think.

Best wishes,

D
Zaphod
Posts: 78
Joined: Sat 23 Jun 2018, 15:51

Re: Screen dimensions

Post by Zaphod »

Not sure it gives any more information but I think that could be written a little more concisely using structures.

Code: Select all

            DISPLAY_DEVICE_ATTACHED_TO_DESKTOP=1
      DIM displaydeviceA{cb%,devicename&(31),devicestring&(127),stateflags%,deviceid&(127),devicekey&(127)}
      displaydeviceA.cb%=DIM(displaydeviceA{})
      DIM buf% 33
      REPEAT
        SYS"EnumDisplayDevicesA",0,I%,displaydeviceA{},1 TO success%
        I%+=1
        IF displaydeviceA.stateflags% AND DISPLAY_DEVICE_ATTACHED_TO_DESKTOP=1 THEN
          PRINT displaydeviceA.devicename&()
          PRINT displaydeviceA.devicestring&()
          PRINT displaydeviceA.stateflags%
          $$buf%=displaydeviceA.devicename&()
          SYS"EnumDisplayDevicesA",buf%,0,displaydeviceA{},1 TO success%
          PRINT displaydeviceA.devicestring&()
          PRINT
        ENDIF
      UNTIL success%=FALSE

Zaphod
Posts: 78
Joined: Sat 23 Jun 2018, 15:51

Re: Screen dimensions

Post by Zaphod »

I had a play trying various ways to achieve what you were after but without success.
Win 32 calls to MonitorFromPoint always failed. Calls to MonitorFromRect always gave the handle of the primary monitor no mater what Rect coordinates were given. So I could never get a handle to the second monitor, which would allow me to determine its size, but even then I am not sure that would help.
I tried just writing a simple dialog to a position I knew was on the second monitor. It always put it the at the far edge of the primary rather than onto the secondary monitor.
Whether any of that is related to Windows 10 or the Nvidia drivers I can't say. Perhaps it was that I was running from the IDE that constrains things.
Edit: It relates to the way Windows works and it places things on the monitor that contains the primary window by default.
Z
Last edited by Zaphod on Sat 09 Feb 2019, 13:47, edited 1 time in total.
User avatar
hellomike
Posts: 192
Joined: Sat 09 Jun 2018, 09:47
Location: Amsterdam

Re: Screen dimensions

Post by hellomike »

Hi,

Actually I don't understand how the modification done by DDRM does give a reasonable output and not a crash since the structure doesn't seem in the correct format.

DIM displaydeviceA{cb%,devicename%,devicestring%,stateflags%,deviceid%,devicekey%}

defines a structure of 4+4+4+4+4+4=24 bytes, while the call to the EnumDisplayDevicesA function expects a structure in memory of 4+32+128+4+128+128 bytes. Would the call not overwrite byte 5 - 23 (and beyond) with the actual characters in Device Name?

How come that after the SYS call like e.g.

^displaydeviceA.devicename%

points to a printable string?

I understand Zaphod's program and structure declaration but not the other.

Thanks

Mike