//monitor 显示器 namespace sys.monitor; class MONITORINFO { INT cbSize = 40; struct rcMonitor = { int left; int top; int right; int bottom; }; struct rcWork = { int left; int top; int right; int bottom; }; INT flags; } class MONITORINFOEX{ ctor(){ this = MONITORINFO(); this.cbSize = 104; }; WORD deviceName[32]; eachDevice = $eachDevice; } MONITORINFOEX.MONITORINFO = MONITORINFO; MONITORINFOEX.$eachDevice = function(){ return eachDevice(1,owner.deviceName); } getInfo = function(hm){ var info = MONITORINFO(); if( hm ? ::User32.GetMonitorInfo( hm,info ) ) return info; } getInfoEx = function(hm){ var info = MONITORINFOEX(); if( hm ? ::User32.GetMonitorInfo( hm,info ) ) return info; } getInfoFromWindow = function(hwnd=0,flag = 2/*_MONITOR_DEFAULTTONEAREST*/){ return getInfo( ::User32.MonitorFromWindow( hwnd ,flag ) ); } getInfoFromPoint = function(x,y,flag = 0/*_MONITOR_DEFAULTTONULL*/){ return getInfo( ::User32.MonitorFromPoint ( x,y ,flag) ); } eachInfo = function(hdc,rcClip){ var m = {}; var proc = ..raw.tostdcall(function(hMonitor,hdcMonitor,rcMoninter,data){ var info = MONITORINFOEX(); if( ::User32.GetMonitorInfo( hMonitor,info ) ){ if( m[hMonitor] && info.flags == 1/*_MONITORINFOF_PRIMARY*/ ) return false; if( rcMoninter ) info.rc = ..raw.convert(rcMoninter,{int left;int top;int right;int bottom}); info.hdc = hdc; m[hMonitor] = info; } return true; },"bool(ptr,ptr,ptr,ptr)"); ::User32.EnumDisplayMonitors(hdc,rcClip,proc,0); return function(hMonitor){ return ..table.next(m,hMonitor); } } class DISPLAY_DEVICE{ INT cbSize=840; WORD deviceName[32]; WORD deviceString[128]; INT stateFlags; WORD deviceId[128]; WORD deviceKey[128]; } eachDevice = function(flags,deviceName){ var idx = 0; return function(){ var device = DISPLAY_DEVICE(); if( ::User32.EnumDisplayDevicesW(deviceName,idx,device,flags) ){ idx++; if(flags && #device.deviceId){ var idStr = ..string.split(device.deviceId,"#"); device.deviceId2 = idStr[3]; } return device; } } } class DEVMODE_DISPLAY_DEVICE{ WORD deviceName[0x20/*_CCHDEVICENAME*/]; WORD specVersion; WORD driverVersion; WORD size = 220; WORD driverExtra; INT fields; struct position = {INT x;INT y;} INT displayOrientation; INT displayFixedOutput; word color; word duplex; word yResolution; word ttOption; word collate; WORD formName[0x20/*_CCHFORMNAME*/]; WORD logPixels; INT bitsPerPel; INT pelsWidth; INT pelsHeight; INT displayFlags; INT displayFrequency; INT icmMethod; INT icmIntent; INT mediaType; INT ditherType; INT reserved1; INT reserved2; INT panningWidth; INT panningHeight; } eachMode = function(flags,deviceName){ var idx = 0; return function(){ var devMode = DEVMODE_DISPLAY_DEVICE(); if( ::User32.EnumDisplaySettingsExW(deviceName,idx,devMode,flags) ){ idx++; return devMode; } } } changeMode = function(mode,flags,deviceName){ if(mode){ if(!mode[["_struct"]]) { mode = ..table.assign( DEVMODE_DISPLAY_DEVICE(),mode ); } if(mode.fields===null) mode.fields = 0; if(mode.pelsWidth!==null) mode.fields = mode.fields | 0x80000/*_DM_PELSWIDTH*/; if(mode.pelsHeight!==null) mode.fields = mode.fields | 0x100000/*_DM_PELSHEIGHT*/; if(mode.bitsPerPel!==null) mode.fields = mode.fields | 0x40000/*_DM_BITSPERPEL*/; if(mode.displayOrientation!==null) mode.fields = mode.fields | 0x80/*_DM_DISPLAYORIENTATION*/ if(mode.displayFlags!==null) mode.fields = mode.fields | 0x00200000/*_DM_DISPLAYFLAGS*/ if(mode.position!==null) mode.fields = mode.fields | 0x00000020/*_DM_POSITION */ if(mode.videoParameters){ flags = (flags:0) | 0x20/*_CDS_VIDEOPARAMETERS*/ } } //https://learn.microsoft.com/windows/win32/api/winuser/nf-winuser-changedisplaysettingsexw return ::User32.ChangeDisplaySettingsExW(deviceName,mode,null,flags,mode[["videoParameters"]]); } /*****intellisense() sys.monitor = 显示器函数库。\n相关库: com.monitor, sys.display, sys.ddcci 。 end intellisense*****/ /**intellisense(sys.monitor) getInfo(.(hMonitor) = 参数为显示设备句柄\n返回显示器信息 getInfo() = !MONITORINFO. getInfoFromPoint(.(x,y) = 获取指定坐标所在显示器信息,\所有参数可选 getInfoFromPoint() = !MONITORINFO. getInfoFromWindow(.(窗口句柄) = 获取窗口所在显示器信息,\所有参数可选 getInfoFromWindow() = !MONITORINFO. eachMode(flags,deviceName) = @for( devMode in sys.monitor.eachMode() ){ if( devMode.pelsWidth > (devMode.pelsWidth > devMode.pelsHeight ? 640 : 480) ){ __/*遍历显示器支持的模式,\n所有参考可选,用法请参考此函数源码。\n可通过 sys.monitor.eachDevice 获取可用 deviceName*/ } } eachDevice(flags,deviceName) = @for( dev in sys.monitor.eachDevice(1) ){ __/*如果不指定参数则遍历所有显示适配器。\n如果参数 @2 指定适配置的设备名( eachMode 或 eachDevice 遍历返回对象的 deviceName 字段),\n则遍历该适配器上的所有显示器设备。\n\n如果指定了参数 @2 ,且参数 @1 值为 1,\n则遍历返回对象的 deviceId2 字段为设备 ID。*/ } eachInfo(hdc,rcClip) = @for( hMonitor,monitorInfo in sys.monitor.eachInfo() ){ __/*用法请参考此函数源码*/ } eachInfo() = !MONITORINFO. eachMode() = !DEVMODE_DISPLAY_DEVICE. eachDevice() = !DISPLAY_DEVICE. changeMode( = 修改显示器设置 changeMode(.(mode,flags,deviceName) = 修改显示器设置\n参数 @mode 指定 DEVMODE_DISPLAY_DEVICE 结构体,\n @mode 也可以传一个普通表,仅指定部分需要更新的结构体字段。也可以使用 sys.monitor.eachMode 获取的结构体作为参数 @mode。\n省略 @mode 与 @flags 恢复默认设置。\n\n@flags 可省略,该值可使用 _CDS_ 前缀的常量指定,默认为 0。\n\n@deviceName 指定显示器名,省略则设置默认显示器。\n可用 sys.monitor.eachDevice 获取可用 deviceName\n用法请参考 API 函数 ::User32.ChangeDisplaySettingsExW 的文档 end intellisense**/ /**intellisense() _MONITOR_DEFAULTTONULL=@0/*_MONITOR_DEFAULTTONULL*/ _MONITOR_DEFAULTTOPRIMARY=@1/*_MONITOR_DEFAULTTOPRIMARY*/ _MONITOR_DEFAULTTONEAREST=@2/*_MONITOR_DEFAULTTONEAREST*/ _DMDO_DEFAULT=@0/*_DMDO_DEFAULT*/ _DMDO_90=@1/*_DMDO_90*/ _DMDO_180=@2/*_DMDO_180*/ _DMDO_270=@3/*_DMDO_270*/ _ENUM_CURRENT_SETTINGS=@-1/*_ENUM_CURRENT_SETTINGS*/ _ENUM_REGISTRY_SETTINGS=@-2/*_ENUM_REGISTRY_SETTINGS*/ _EDS_RAWMODE=@0x2/*_EDS_RAWMODE*/ _CDS_UPDATEREGISTRY=@1/*_CDS_UPDATEREGISTRY*/ _CDS_TEST=@2/*_CDS_TEST*/ _CDS_FULLSCREEN=@4/*_CDS_FULLSCREEN*/ _CDS_GLOBAL=@8/*_CDS_GLOBAL*/ _CDS_SET_PRIMARY=@0x10/*_CDS_SET_PRIMARY*/ _CDS_VIDEOPARAMETERS=@0x20/*_CDS_VIDEOPARAMETERS*/ _CDS_ENABLE_UNSAFE_MODES=@0x100/*_CDS_ENABLE_UNSAFE_MODES*/ _CDS_DISABLE_UNSAFE_MODES=@0x200/*_CDS_DISABLE_UNSAFE_MODES*/ _CDS_RESET=@0x40000000/*_CDS_RESET*/ _CDS_RESET_EX=@0x20000000/*_CDS_RESET_EX*/ _CDS_NORESET=@0x10000000/*_CDS_NORESET*/ _MONITORINFOF_PRIMARY=@1/*_MONITORINFOF_PRIMARY*/ _DISPLAY_DEVICE_ACTIVE=@1/*_DISPLAY_DEVICE_ACTIVE*/ _DISPLAY_DEVICE_MIRRORING_DRIVER=@8/*_DISPLAY_DEVICE_MIRRORING_DRIVER*/ _DISPLAY_DEVICE_MODESPRUNED=@0x8000000/*_DISPLAY_DEVICE_MODESPRUNED*/ _DISPLAY_DEVICE_PRIMARY_DEVICE=@4/*_DISPLAY_DEVICE_PRIMARY_DEVICE*/ _DISPLAY_DEVICE_REMOVABLE=@0x20/*_DISPLAY_DEVICE_REMOVABLE*/ _DISPLAY_DEVICE_VGA_COMPATIBLE=@0x10/*_DISPLAY_DEVICE_VGA_COMPATIBLE*/ end intellisense**/ /**intellisense(!MONITORINFO) rcMonitor = 显示器的在屏幕坐标系中的矩形\n!rect. rcWork = 显示器的工作区域\n!rect. flags = 该值为1时为主显示器 deviceName = 仅 sys.monitor.getInfoEx 或 sys.monitor.eachInfo 函数会返回该值 eachDevice() = @for dev in ??.eachDevice() {\n __/*遍历此适配器上的所有显示器设备。 \n则遍历返回对象的 deviceId2 字段为设备 ID。*/\n}\n!DISPLAY_DEVICE. end intellisense**/ /**intellisense(!DEVMODE_DISPLAY_DEVICE) pelsWidth = 像素宽度 pelsHeight = 像素高度 bitsPerPel = 像素位宽 displayOrientation = 显示方向,参考_DMDO_ 前缀常量 displayFrequency = 刷新频率 end intellisense**/ /*****intellisense(!DISPLAY_DEVICE) deviceName = 适配器设备或监视器设备的设备名 deviceString = 显示适配器或显示监视器的描述 stateFlags = 设备状态标志。\n_DISPLAY_DEVICE 前缀常量数值或这些数值的组合 deviceId = 设备 ID。\n典型的格式为 \\.\DISPLAY### deviceId2 = 设备 ID。\n仅保留 deviceId 字段的 部分。\n可通用于 com.monitor 的设备 ID 参数。 deviceKey = 设备在注册表中的键路径,主要用于获取和配置设备的详细信息。 end intellisense*****/