HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2019
1109
ゆうやんChangeDisplaySettingsで解像度を変更したい10解決


ゆうやん

リンク

2019/11/9(Sat) 23:07:44|NO.88825

chgdisp命令を使わず、ChangeDisplaySettings関数で解像度を変更したいのですがうまくいきません。
どこか間違っているのでしょうか?
いろいろ調べてみてみたのですが、全然見つかりませんでした。

#uselib "user32.dll" #cfunc EnumDisplaySettings "EnumDisplaySettingsA" int,int,var #func ChangeDisplaySettings "ChangeDisplaySettingsA" var,int #define ENUM_CURRENT_SETTINGS -1 #define CDS_FULLSCREEN 4 dim mode,2 res=EnumDisplaySettings(0,ENUM_CURRENT_SETTINGS,mode) mode.0=640 mode.1=480 mes res ChangeDisplaySettings mode,CDS_FULLSCREEN



この記事に返信する


K-s

リンク

2019/11/11(Mon) 17:15:34|NO.88838

EnumDisplaySettings の第3引数に指定する mode の配列要素数が足りていないです。
それと解像度を指定する配列のインデックスは 27 と 28 ですね。

#uselib "user32.dll" #cfunc EnumDisplaySettings "EnumDisplaySettingsA" int,int,var #func ChangeDisplaySettings "ChangeDisplaySettingsA" var,int #define ENUM_CURRENT_SETTINGS -1 #define CDS_FULLSCREEN 4 dim mode,40 ; 40あればたぶん大丈夫… res=EnumDisplaySettings(0,ENUM_CURRENT_SETTINGS,mode) mode.27=640 mode.28=480 mes res ChangeDisplaySettings mode,CDS_FULLSCREEN mes stat ; 0 以外だと失敗しています
解像度などは環境によって指定できる値が決まっていてそれ以外の値を指定すると失敗します。
どんな値ならOKなのかは EnumDisplaySettings で調べることができるので下のページ参考にしてみてください。
https://blog.goo.ne.jp/hiro239415/e/06ae28612ce2f1dc2e6aff9afadc8ef9



ゆうやん

リンク

2019/11/11(Mon) 19:56:05|NO.88841

>K-sさん
ありがとうございます。
この関数を使って、サブモニターの解像度を変更することはできないのでしょうか?



K-s

リンク

2019/11/12(Tue) 17:47:10|NO.88844

似た関数に ChangeDisplaySettingsEx というのがあるんですがこれでサブモニターも変更できます。
その際モニターのハンドルが必要なので別の関数を使ってハンドル得る必要があります。
前にサブモニターの解像度変更サンプル作ったことがあるので参考にしてみてください。
https://uchitsukushi2.hatenablog.jp/entry/2016/06/19/192459



ゆうやん

リンク

2019/11/13(Wed) 21:48:21|NO.88857

>K-sさん。
ありがとうございます。
ChangeDisplaySettingsEx関数を使う方法もあるんですね。
MonitorFromPoint関数を使わず、すべてのモニターのハンドルを取得する方法はないのでしょうか?
調べても出て来なかったので・・・。



K-s

リンク

2019/11/14(Thu) 13:25:41|NO.88862

すいません勘違いしてました、モニタのハンドルは必要ないです…
必要なのはデバイス名で EnumDisplayDevices という関数で取得できます。
一応モニタのハンドルは EnumDisplayMonitors でコールバック使って列挙できます。
デバイス名が分かれば EnumDisplaySettings や ChangeDisplaySettingsEx に渡せば
解像度変更できると思います。

解像度表示のだけのサンプルですが
EnumDisplayDevices 版

#include "user32.as" #const DISPLAY_DEVICE_ACTIVE 1 #const DISPLAY_DEVICE_PRIMARY_DEVICE 4 #const ENUM_CURRENT_SETTINGS -1 dim dd, 106 ; DISPLAY_DEVICE dd = 424 ; cb p = varptr(dd) dupptr name, p + 4, 32, 2 ; DeviceName dupptr flag, p + 164, 4, 4 ; StateFlags dim dm, 40 ; DEVMODE p = varptr(dm) dupptr resX, p + 108, 4, 4 ; dmPelsWidth dupptr resY, p + 112, 4, 4 ; dmPelsHeight repeat if EnumDisplayDevices(0, cnt, varptr(dd), 0) == 0 : break if flag & DISPLAY_DEVICE_ACTIVE { mes name if flag & DISPLAY_DEVICE_PRIMARY_DEVICE { mes "メインディスプレイ" } EnumDisplaySettings name, ENUM_CURRENT_SETTINGS, varptr(dm) mes strf("解像度 %d×%d\n", resX, resY) } loop

EnumDisplayMonitors 版

#include "user32.as" #include "modclbk3.hsp" #const ENUM_CURRENT_SETTINGS -1 dim mi, 18 ; MONITORINFOEX mi = 72 ; cbSize p = varptr(mi) dupptr flag, p + 36, 4, 4 ; dwFlags dupptr name, p + 40, 32, 2 ; szDevice dim dm, 40 ; DEVMODE p = varptr(dm) dupptr resX, p + 108, 4, 4 ; dmPelsWidth dupptr resY, p + 112, 4, 4 ; dmPelsHeight newclbk3 clbk, 4, *MonitorEnumProc EnumDisplayMonitors 0, 0, clbk, 0 stop *MonitorEnumProc clbkargprotect prm GetMonitorInfo prm, varptr(mi) mes name if flag { mes "メインディスプレイ" } EnumDisplaySettings name, ENUM_CURRENT_SETTINGS, varptr(dm) mes strf("解像度 %d×%d\n", resX, resY) return 1



ゆうやん

リンク

2019/11/16(Sat) 15:49:33|NO.88871

おお、ありがとうございます。
EnumDisplayDevicesやGetMonitorInfoでモニターの解像度を取得できるのはわかったのですが、
モニターの座標とか取得できないのでしょうか?
解像度の変更は、主に全画面のゲームを作りたいと考えているので・・・。



K-s

リンク

2019/11/17(Sun) 12:23:47|NO.88872

GetMonitorInfo で得られる MONITORINFO 構造体の rcMonitor、
EnumDisplaySettings で得られる DEVMODE 構造体の dmPosition にそれぞれ座標が入っています。
ただ MONITORINFO の方は DPI によって座標が変わり DEVMODE は DPI によらず一定という違いがあるので注意してください。

あとメインモニタ以外は解像度を変えるとそれに応じて座標も変わるので
1.モニタ解像度変更
2.モニタ座標取得
3.ウィンドウの移動・サイズやスタイル変更等
という順番になると思います。



ゆうやん

リンク

2019/11/23(Sat) 17:51:53|NO.88911

こんな感じでいいのでしょうか?

#uselib "user32.dll" #cfunc MonitorFromWindow "MonitorFromWindow" int,int #func GetMonitorInfo "GetMonitorInfoA" int,var #func EnumDisplaySettings "EnumDisplaySettingsA" sptr,int,var #func ChangeDisplaySettings "ChangeDisplaySettingsA" int,int #func ChangeDisplaySettingsEx "ChangeDisplaySettingsExA" sptr,int,int,int,int #func ShowCursor "ShowCursor" int #func SetCursorPos "SetCursorPos" int,int ;ここに全画面表示したいサイズを変える。パソコンの解像度には制約があり、失敗することもある。 #define sizex 1024 #define sizey 768 ;一瞬だけウィンドウが表示されないようにする処理 #packopt hide 1 #define CDS_UPDATEREGISTRY 0x01 #define ENUM_CURRENT_SETTINGS -1 #define CDS_FULLSCREEN 4 #define DM_POSITION 0x00000020 screen 0,400,100 onkey *kettei mes "全画面表示にしたいモニターにウィンドウを移動させ、\nEnterキーを押してください。" stop *kettei if wparam!13:stop dim mode,40 MainMoni = MonitorFromWindow(hwnd,0);ウィンドウ座標から、モニターのハンドルを取得する。 dim MonitorData,72/4 MonitorData(0) = 72 GetMonitorInfo MainMoni,MonitorData if stat=0:dialog "モニター情報の取得に失敗しました。",1:end sdim DispName,32 memcpy DispName,MonitorData,32,0,40 EnumDisplaySettings DispName,ENUM_CURRENT_SETTINGS,mode if stat=0:dialog "モニターが見つかりませんでした。",1:end ;解像度を800x600に変更 mode.27=sizex mode.28=sizey ChangeDisplaySettingsEx DispName,varptr(mode),0,CDS_FULLSCREEN,0 if stat:dialog "解像度の変更に失敗しました。",1:end dim MonitorData,72/4 MonitorData(0) = 72 GetMonitorInfo MainMoni,MonitorData if stat=0:dialog "モニター情報の取得に失敗しました。",1:end bgscr 0,sizex,sizey,2,MonitorData(1),MonitorData(2) sdim DispName,32 memcpy DispName,MonitorData,32,0,40 mes "DisplayName = "+DispName mes "モニター座標X(左基準)"+MonitorData(1) mes "モニター座標Y(上基準)"+MonitorData(2) mes "Alt + F4 で終了\n終了すると元に戻ります。" gsel 0,2 ;マルチモニター環境でmouse命令を使うとマウスカーソルが消えてしまうため、代わりにShowCursor関数を使うこと。 ;マウスカーソルの移動は、mouse命令でマイナス位置に移動することができないため、代わりにSetCursorPos関数を使うこと。 ;モニターの中央に指定 mx=MonitorData(1)+(sizex/2) my=MonitorData(2)+(sizey/2) repeat SetCursorPos mx,my;マウスカーソルをモニターの中央に移動する。 if ginfo_mx=mx & ginfo_my=my:break loop wait 500 ShowCursor 0;カーソルの非表示 wait 1000 ShowCursor 1;カーソルの表示 /* wait 1000 ;解像度を元に戻す ChangeDisplaySettingsEx DispName,0,0,CDS_FULLSCREEN,0 gsel 0,-1 */ stop



K-s

リンク

2019/11/24(Sun) 20:29:47|NO.88923

いいと思います。こちらの環境でもちゃんと解像度変更できました。

;モニターの中央に指定 mx=MonitorData(1)+(sizex/2) my=MonitorData(2)+(sizey/2)
これは表示スケール(DPI)の大きいモニタだとズレるので

;モニターの中央に指定 mx=(MonitorData(1)+(MonitorData(3))/2 my=(MonitorData(2)+(MonitorData(4))/2
これでモニタの真ん中に来ます。



ゆうやん

リンク

2019/11/27(Wed) 20:51:30|NO.88931

>K-sさん
ありがとうございます。
chgdisp命令だと、メインモニターでしか解像度の変更ができないみたいなので、Win32APIを使ってサブモニターの解像度を変更しようと考えてました。
わからないことがあれば、質問するかもしれませんが、その時はよろしくお願いします。



ONION software Copyright 1997-2023(c) All rights reserved.