UWSCでGetMonitorInfoにMONITORINFOEXを渡す
UWSCでWin32APIのGetMonitorInfoにMONITORINFOEXを渡す方法がわからない、という質問をいただいたので、その回答です。
素のUWSCで、真面目にやるなら、
DEF_DLL GetMonitorInfoW(DWORD,{long,long,...,wchar,wchar,...}): BOOL: user32
「long,long,...」はlongを10個。「wchar,wchar,...」はwcharを32個書いてください。
これで多分、上手くいきます。(未検証)
もちろん、引数も42+1個書いてくださいね!
誰がそんなことするか!
横着定義
基本は横着定義です。
まー、簡単に言えば、GetMonitorInfoWの第二引数は104Byteのメモリーを確保したポインターを渡せば良いです。
(DWORD相当10個と、WCHARが32個。4*10+2*32=104Byte)
なので、long[25](UWSCはこう書くと0~25まで使える。すなわち26個分確保される)を渡せば良いことになります。
この辺を詳しく知りたいなら、UWSCのDEF_DLLについて - じゅんじゅんのきまぐれでも読んで。
ということで以下のような感じ。
DEF_DLL MonitorFromPoint(long,long,DWORD): DWORD: user32 DEF_DLL GetMonitorInfoW(DWORD,long[]): BOOL: user32 DEF_DLL RtlMoveMemory(var pwchar,long[],DWORD): kernel32 CONST MONITORINFO_SIZE = 40 CONST LONG_SIZE = 4 CONST CCHDEVICENAME = 32 CONST WCHAR_SIZE = 2 DIM i, x, y, inf[MONITORINFO_SIZE / LONG_SIZE - 1 + CCHDEVICENAME / LONG_SIZE * WCHAR_SIZE], device inf[0] = MONITORINFO_SIZE + CCHDEVICENAME * WCHAR_SIZE FOR i = 0 TO MONITOR() - 1 x = MONITOR(i, MON_X) y = MONITOR(i, MON_Y) IFB GetMonitorInfoW(MonitorFromPoint(x, y, 0), inf) THEN // 0:MONITOR_DEFAULTTONULL device = FORMAT(CHR(0), inf[0] / WCHAR_SIZE) RtlMoveMemory(device, inf, inf[0]) // 一旦構造体全体を文字列として解釈 device = COPY(device, MONITORINFO_SIZE / WCHAR_SIZE + 1) // MONITORINFO部分をカットする PRINT "(" + inf[1] + "," + inf[2] + ")-(" + inf[3] + "," + inf[4] + ") (" + inf[5] + "," + inf[6] + ")-(" + inf[7] + "," + inf[8] + ") " + inf[9] + " " + device ENDIF NEXT
szDevice部分を取り出すのに少し工夫が必要ですね。
美しくない
上記の問題点は、inf[1]とか参照が美しくないことにあります。
以前、 UWSCで構造体を使う - じゅんじゅんのきまぐれ というものを書きました。
これですよ。
これならちゃんと.参照で書けますし、szDeviceを取り出すのも簡単です。
ただ、ダサいことにStructモジュールがUnicode対応していないので、GetMonitorInfoAを使います。
CALL Struct.uws DEF_DLL MonitorFromPoint(long,long,DWORD): DWORD: user32 DEF_DLL GetMonitorInfoA(DWORD,DWORD): BOOL: user32 DIM name = "RECT" TEXTBLOCK _rect_struct { left: ['long'], top: ['long'], right: ['long'], bottom: ['long'] } ENDTEXTBLOCK Struct.Define(name, _rect_struct) name = "MONITORINFOEX" TEXTBLOCK _monitorinfoex_struct { cbSize:['DWORD'], rcMonitor:['RECT'], rcWork:['RECT'], dwFlags:['DWORD'], szDevice:['char', null, 32] } ENDTEXTBLOCK DIM i, x, y, inf, pInf inf = Struct.Create(name, _monitorinfoex_struct) inf.cbSize = Struct.GetSize(name, inf) pInf = Struct.Alloc(inf) FOR i = 0 TO MONITOR() - 1 x = MONITOR(i, MON_X) y = MONITOR(i, MON_Y) IFB GetMonitorInfoA(MonitorFromPoint(x, y, 0), pInf) THEN // 0:MONITOR_DEFAULTTONULL Struct.Update(inf, pInf) PRINT "(" + inf.rcMonitor.left + "," + inf.rcMonitor.top + ")-(" + inf.rcMonitor.right + "," + inf.rcMonitor.bottom + ") (" + inf.rcWork.left + "," + inf.rcWork.top + ")-(" + inf.rcWork.right + "," + inf.rcWork.bottom + ") " + inf.dwFlags + " " + inf.szDevice ENDIF NEXT Struct.Dispose()
cbSizeもきれいに書けるので嬉しい限りです。