1. Second monitor enumeration

First - I use Eu3 and Win32Lib.

i am running my program with an extended desktop, and a DLP projector plugged in for the program to use. I do that to use 100% of the DLP output, no taskbar etc. I am trying to find out the parameters of the DLP plugged in - width & height, whether it's on or not, etc. This can be done according to the Windows API with EnumDisplayDevicesA which is part of user32.dll. I can register the function, which seems to be OK. I'm running it with more or less no parameters other than the monitor device index. However, whenever I call the function it returns True which implies there is a monitor connected, as far as I can see. And it does that whatever device index I use. 0 is for the main screen - which always exists - but with 1 or 2 etc it STILL returns True implying that the monitor is there and it isn't. It ought to return False. IMHO.

So can anyone with experience of connecting the Win API into Euphoria assist me? It's not an area I have any real experience with; I'm a programmer who codes to do a job rather than coding to get a coding environment to work in. And 98% of my coding is for microcontrollers in C, so I am out of my depth.

I live in hope ...

new topic     » topic index » view message » categorize

2. Re: Second monitor enumeration

How are you "wrapping" the call?

It's hard to guess what the problem might be without an example. Are you passing a null as the first parameter and the monitor # as the second?

new topic     » goto parent     » topic index » view message » categorize

3. Re: Second monitor enumeration

irv said...

How are you "wrapping" the call?

It's hard to guess what the problem might be without an example. Are you passing a null as the first parameter and the monitor # as the second?

I should have put this in originally. It is a very basic call based upon other Win32Lib function registering. I assumed that merely giving some space for a buffer would be adequate, and passing the pointer, would do. I didn't progress further because I thought that if I can get a return boolean to reflect whether there is a monitor there or not then I was on the right track. If not, i wasn't. And i wasn't.

 
atom     ddptr 
integer  ddret 
sequence ddbuff 
 
constant xEnumDisplayDevicesA = registerw32Function(user32, "EnumDisplayDevicesA", {C_POINTER, C_LONG, C_POINTER, C_LONG}, C_UINT) 
 
trace(1) 
 
ddbuff    = repeat(0, 424) 
ddbuff[1] = 424 
ddptr     = w32acquire_mem(0, ddbuff) 
 
ddret     = w32Func(xEnumDisplayDevicesA, {VOID, 1, ddptr, 1}) -- I also tried NULL where I have VOID 
 
release_mem(ddptr) 
 

Is this a valid way to call the function??

new topic     » goto parent     » topic index » view message » categorize

4. Re: Second monitor enumeration

Looking at the DISPLAY_DEVICEA structure, I see that the width & height are not there. I shall have to call EnumDisplaySettingsA function apparently with the name of the monitor ... this is all getting very complicated. All I want to do is get the width and height of any second or third monitor, and ideally whether it is on or not.

This is a subtle call for more advice over and above the previous query. It's one of those subjects which seems to be completely missing in the Win32Lib scenario. It seems these days that communication via the internet is of far greater interest than purely internal programming.

So again - any advice received gratefully...

Andy

new topic     » goto parent     » topic index » view message » categorize

5. Re: Second monitor enumeration

AndyDrummond said...

ddret     = w32Func(xEnumDisplayDevicesA, {VOID, 1, ddptr, 1}) -- I also tried NULL where I have VOID 

Is this a valid way to call the function??

Don't ever use VOID like that. It is a "junkyard", and will contain whatever crud from who-knows-what. Use NULL instead.

I've not done much with multiple monitors (and gave up on win32lib a looooooooooonnnngg time ago) so I can't go much beyond this, but it's a start:

constant sizeDD = 424, 
         DD_DeviceName = 4, 
         DD_DeviceString = 36, 
         DD_StateFlags = 164, 
         pDD = allocate(sizeDD), 
         EDD_GET_DEVICE_INTERFACE_NAME = 1, 
         user32 = open_dll("user32.dll"), 
         xEnumDisplayDevices = define_c_func(user32,"EnumDisplayDevicesA",{C_PTR,C_DWORD,C_PTR,C_DWORD},C_BOOL) 
 
mem_set(pDD,0,sizeDD) 
poke4(pDD,sizeDD) 
for iDevNum=0 to 9999 do 
    if not c_func(xEnumDisplayDevices,{NULL,iDevNum,pDD,EDD_GET_DEVICE_INTERFACE_NAME}) then exit end if 
    string device_name = peek_string(pDD+DD_DeviceName) 
    ?device_name 
    atom pDeviceName = allocate_string(device_name) 
    printf(1,"flags:%x\n",peek4u(pDD+DD_StateFlags)) 
    for jDevNum=0 to 9999 do 
        if not c_func(xEnumDisplayDevices,{pDeviceName,jDevNum,pDD,EDD_GET_DEVICE_INTERFACE_NAME}) then exit end if 
        ?peek_string(pDD+DD_DeviceName) 
        ?peek_string(pDD+DD_DeviceString) 
        printf(1,"flags:%x\n",peek4u(pDD+DD_StateFlags)) 
    end for 
    ?"===" 
end for 

I get

"\\\\.\\DISPLAY1" 
flags:8000005 
"\\\\.\\DISPLAY1\\Monitor0" 
"BenQ GL2450H" 
flags:3 
"===" 
"\\\\.\\DISPLAY2" 
flags:8000000 
"===" 
I suspect I do indeed have two adapters but only one physical display device. I don't know what the flags are, and as you say there is no width/height, so... I am probably using EDD_GET_DEVICE_INTERFACE_NAME all wrong to boot.

new topic     » goto parent     » topic index » view message » categorize

6. Re: Second monitor enumeration

Pete, thank you. That puts me on the right foot for getting the rest of the information I need.

As to using VOID; I used NULL originally but when I got duff results I tried VOID, just because ... I see what you mean completely. Data graveyard.

I will give this a go ASAP and hopefully won't need any more help (famous last words!)

Andy

new topic     » goto parent     » topic index » view message » categorize

7. Re: Second monitor enumeration

I am now having trouble with Windows ENUM_DEVICE_SETTINGS. I need to set up the DEVMODE structure to pass into the call, but though I have got the Windows SDK installed I can't get the size value properly (i think that's the trouble) so i have gone to an approximate value, and put that in where I think it ought to be. I've been referring to wingdi.h. It always returns False. So if any of you worthies can advise me I'd be very happy. All i need to get is the monitor width & height. Ideally whether it is on or not but that is less important.

The code below is in Eu3 style and uses Win32Lib. I'm old and worn enough that having got a perfectly satisfactory way of writing code for Windows with Judith's IDE I really don't want to start learning a relatively minor variant of it.

The code below is just a "proof of concept" style which is why I haven't freed any allocations up. And I am only interested in the second monitor after the prime screen. The monitor name is also a bit odd ... the output I get is below. The chatty name is just a generic so of no use for specifying.

So as before any help is appreciated. And if Pete Lomax sees this - you put me on the right path even if I can't get to the end, so thanks again.

Call 1:  Device name: \\.\DISPLAY1 
Call 2:  Device name: \\.\DISPLAY1\Monitor0 
EnumDisplaySettings call failed 
Call 1:  Device name: \\.\DISPLAY2 
Call 2:  Device name: \\.\DISPLAY2\Monitor0 
EnumDisplaySettings call failed 
 

with trace 
include Win32Lib.w 
 
--========================  DATA  ============================ 
 
 
constant sizeDD = 424, 
         DD_DeviceName = 4, 
         DD_DeviceString = 36, 
         DD_StateFlags = 164, 
         pDD = allocate(sizeDD), 
         EDD_GET_DEVICE_INTERFACE_NAME = 1, 
          
         user32 = open_dll("user32.dll"), 
         xEnumDisplayDevices = define_c_func(user32,"EnumDisplayDevicesA",{C_POINTER,C_ULONG,C_POINTER,C_ULONG},C_INT), 
         xEnumDisplaySettings = define_c_func(user32,"EnumDisplaySettingsA",{C_POINTER,C_ULONG,C_POINTER},C_INT) 
 
constant sizeDM = 128,	-- This is too big I think - I got 113, not a lot of goof 
	 DM_Size = 32,	-- Where size word held 
	 pDM = allocate(sizeDM) 
 
 
sequence device_name, display_name, display_string, safe 
atom pDeviceName 
 
--=====================  CODE  ======================== 
 
mem_set(pDD, 0, sizeDD) 
poke4  (pDD, sizeDD) 
 
mem_set(pDM, 0, sizeDM) 
poke4  (pDM+DM_Size, sizeDM) 
 
for iDevNum=0 to 1 do 
 
--	First call to get adapter name 
 
    if not c_func(xEnumDisplayDevices, {NULL, iDevNum, pDD, EDD_GET_DEVICE_INTERFACE_NAME}) then 
    	exit 
    end if 
 
    device_name = peek_string(pDD+DD_DeviceName) 
    puts(Screen, "Call 1:  Device name: " & device_name & "\n") 
 
--	Next call to get monitor name 
 
    pDeviceName = allocate_string(device_name) 
 
    if not c_func(xEnumDisplayDevices,{pDeviceName, 0, pDD, EDD_GET_DEVICE_INTERFACE_NAME}) then 
       	printf(1,"EnumDisplayDevices [%s] bad call\n", {safe}) 
   	exit 
    end if 
 
    device_name = peek_string(pDD+DD_DeviceName) 
    safe = device_name 
    puts(Screen, "Call 2:  Device name: " & safe & "\n") 
 
--	Call to get settings for that monitor - or not? 
--	pDD is wrong. refer to wingdi.h: 
--	I need proper values for DEVMODE including length value in [dmSize] etc 
--	I save the monitor name in a Euphoria sequence and re-allocate because somewhere 
--	I read that the string in the DisplayDevices structure gets tromped on 
 
    pDeviceName = allocate_string(safe)	-- Use Euphoria sequence .... 
 
    if not c_func(xEnumDisplaySettings,{pDeviceName, 0, pDM}) then 
	puts(Screen, "EnumDisplaySettings call failed\n") 
    else 
	puts(Screen, "EnumDisplaySettings call succeeded!\n") 
    end if 
 
end for 
 
new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu