トップページ > 過去ログ > 記事閲覧
SetWindowSize関数を用いた結果(解決)
名前:南山まさかず 日時: 2011/11/28 18:51

 普段お世話になっています、南山まさかずと申す ものです。  今回は、Dxライブラリのバグ? と言うか異常現象 らしきものを発見したので、報告させていただきま す。  まず最初に僕の使用している環境ですが、 VC2008EEを使用しております。ライブラリのバージ ョンは3.06cです。  次に、報告する異常現象(他に形容の使用がありま せん)ですが、題名にもあるとおり、SetWindowSize 関数を用いたときに起こります。具体的には、ウィ ンドウのサイズを規定のものから変えたときに起こ ります。  具体例として次のソースを載せておきます(汚い ソースコードですが、とりあえず実行した結果をコ メントの内容と比べていただければ分かるかと思い ます)。 /* Test.cpp このプログラムを実行すると、一見正しい結果になっているように見えますが よくソースコードと比べると時計の高さとウィンドウの高さの比がおかしなことになっています */ #include<fstream> #include<iostream> #include<string> #include<vector> #include<cmath> #include"DxLib.h" using namespace std; typedef basic_string<TCHAR> Tstring; typedef basic_fstream<TCHAR> Tfstream; typedef long long int LLint; const int WINWIDTH=800; //ここの数字を640以外にすると時計のサイズ比がおかしくなる const int WINHIGH=WINWIDTH*3/4; const int FONTSIZE=30; const int FONTWIDTH=0; const long double PI_NUMBER=3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679L; struct WatchData{ public: DATEDATA Time; Tstring Job; bool operator==(const WatchData &data)const{ return (Time.Year==data.Time.Year)&& (Time.Mon==data.Time.Mon)&& (Time.Day==data.Time.Day)&& (Time.Hour==data.Time.Hour)&& (Time.Min==data.Time.Min)&& (Time.Sec==data.Time.Sec)&& (Job==data.Job); } }; int EndNum=0; int DrawWatch(DATEDATA &data){ //時計のサイズはウィンドウの高さの半分のはず if(DrawBox(0,0,WINHIGH/2,WINHIGH/2,GetColor(127,127,127),TRUE)){ throw logic_error("時計の描画に失敗しました"); }int h=data.Hour,m=data.Min,s=data.Sec; int x=WINHIGH/4; if(DrawCircle(x,x,x,GetColor(255,255,255),TRUE)){ throw logic_error("時計の描画に失敗しました"); }if(DrawCircle(x,x,x/10,GetColor(0,0,0),TRUE)){ throw logic_error("時計の描画に失敗しました"); }if(DrawCircle(x,x,x,GetColor(0,0,0),FALSE)){ throw logic_error("時計の描画に失敗しました"); }for(unsigned int i=0;i<60;i++){ if(i%5){ if(DrawLine(static_cast<int>(x*(1+(sin(i*PI_NUMBER/30.0L)))),static_cast<int>(x*(1-(cos(i*PI_NUMBER/30.0L)))),static_cast<int>(x*(1+(0.95L*sin(i*PI_NUMBER/30.0L)))),static_cast<int>(x*(1-(0.95L*cos(i*PI_NUMBER/30.0L)))),GetColor(0,0,0))){ throw logic_error("時計の描画に失敗しました"); } }else{ if(DrawLine(static_cast<int>(x*(1+(sin(i*PI_NUMBER/30.0L)))),static_cast<int>(x*(1-(cos(i*PI_NUMBER/30.0L)))),static_cast<int>(x*(1+(0.9L*sin(i*PI_NUMBER/30.0L)))),static_cast<int>(x*(1-(0.9L*cos(i*PI_NUMBER/30.0L)))),GetColor(0,0,0))){ throw logic_error("時計の描画に失敗しました"); } } }long double th=s/60.0L; int thint=static_cast<int>(th); if(DrawLine(x,x,static_cast<int>(x*(1+(0.8L*sin(2.0L*PI_NUMBER*(th))))),static_cast<int>(x*(1-(0.8L*cos(2.0L*PI_NUMBER*(th))))),GetColor(0,0,0))){ throw logic_error("時計の描画に失敗しました"); }th/=60.0L; th+=m/60.0L; if(DrawLine(x,x,static_cast<int>(x*(1+(0.7L*sin(2.0L*PI_NUMBER*(th))))),static_cast<int>(x*(1-(0.7L*cos(2.0L*PI_NUMBER*(th))))),GetColor(0,0,0))){ throw logic_error("時計の描画に失敗しました"); }th/=12.0L; th+=h/12.0L; if(DrawLine(x,x,static_cast<int>(x*(1+(0.9L*sin(2.0L*PI_NUMBER*(th))))),static_cast<int>(x*(1-(0.9L*cos(2.0L*PI_NUMBER*(th))))),GetColor(0,0,0))){ throw logic_error("時計の描画に失敗しました"); }TCHAR *str=_T("%04d/%02d/%02d %02d:%02d:%02d"); int width=GetDrawFormatStringWidth(str,data.Year,data.Mon,data.Day,data.Hour,data.Min,data.Sec); if(DrawBox(0,2*x,width,2*x+FONTSIZE,GetColor(0,0,0),TRUE)){ throw logic_error("時刻の描画に失敗しました"); }if(DrawFormatString(0,2*x,GetColor(255,255,255),str,data.Year,data.Mon,data.Day,data.Hour,data.Min,data.Sec)){ throw logic_error("時刻の描画に失敗しました"); }return 0; }int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd){ ChangeWindowMode(TRUE); SetOutApplicationLogValidFlag(FALSE); SetWindowText(_T("簡易スケジューラー")); if(DxLib_Init()){ return -1; }try{ if(SetWindowSize(WINWIDTH,WINHIGH)){ throw logic_error("初期化に失敗しました"); }if(SetAlwaysRunFlag(TRUE)){ throw logic_error("初期化に失敗しました"); }if(SetDrawScreen(DX_SCREEN_BACK)){ throw logic_error("初期化に失敗しました"); }if(SetFontSize(FONTSIZE)||SetFontThickness(FONTWIDTH)){ throw logic_error("初期化に失敗しました"); }if(SetKeyInputStringColor( GetColor(0,0,0), GetColor(0,0,127), GetColor(255,255,255), GetColor(0,127,0), GetColor(0,127,127), GetColor(0,127,255), GetColor(0,255,0), GetColor(0,255,127), GetColor(0,255,255), GetColor(127,0,0), GetColor(127,0,127), GetColor(127,0,255) )){ throw logic_error("初期化に失敗しました"); }DATEDATA Time[2]; if(GetDateTime(&Time[0])){ throw logic_error("現在時刻の取得に失敗しました"); }WaitTimer(1000); while(!ProcessMessage()){ if(GetDateTime(&Time[1])){ throw logic_error("現在時刻の取得に失敗しました"); }if(Time[0].Sec!=Time[1].Sec){ if(DrawWatch(Time[1])){ break; }if(GetDateTime(&Time[0])){ throw logic_error("現在時刻の取得に失敗しました"); } }if(CheckHitKey(KEY_INPUT_ESCAPE)){ break; }if((CheckHitKey(KEY_INPUT_LCONTROL)||CheckHitKey(KEY_INPUT_RCONTROL))&&CheckHitKey(KEY_INPUT_P)){ if(SaveDrawScreen(0,0,WINWIDTH,WINHIGH,_T("Watch.bmp"))){ MessageBox(NULL,_T("印刷に失敗しました"),NULL,MB_OK); } }ScreenCopy(); } }catch(logic_error &exc){ printfDx(_T("%s"),exc.what()); ScreenFlip(); MessageBoxA(NULL,exc.what(),NULL,MB_OK); EndNum=1; }catch(exception &exc){ printfDx(_T("%s"),exc.what()); ScreenFlip(); MessageBoxA(NULL,exc.what(),NULL,MB_OK); EndNum=2; }catch(...){ EndNum=3; }DxLib_End(); return EndNum; }  どうも、ウィンドウのサイズを640×480以外にし たとき、「640×480のサイズで一端描画してからそ のあとウィンドウサイズにあわせて拡大縮小する」 ようになっているように見受けられます。  実は以前のバージョン(3.05ぐらい)のときにも 似たような現象は発見していたのですが、そのとき は自作のクラスライブラリを使用していたので、自 分のコードのバグなのかどうか判然としませんでし た。  これはDxライブラリのバグなのでしょうか? それ とも自分のソースコードに問題があるのでしょうか?  どうなっているのでしょうか?

Page: 1 |

Re: SetWindowSize関数を用いた結果 ( No.1 )
名前:いっち 日時:2011/11/07 19:05

おそらく仕様です。 ウィンドウには表面的なサイズと内部的なサイズがあり、SetWindowSize は表面的なサイズを変更するための関数です。 以下のテストコードを実行して手動で表面的なウィンドウのサイズを変更すると、 ウィンドウのサイズに合わせて自動的に文字や四角が拡大縮小されることが分かると思います。 内部的なウィンドウのサイズを変更したい場合は SetGraphMode を使用します。 //- 以下、テストコード -// #include "DxLib.h" int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int ) { ChangeWindowMode( TRUE ); SetWindowText( "DxLib:" DXLIB_VERSION_STR ); SetWindowSizeChangeEnableFlag( TRUE ); if ( DxLib_Init( ) == -1 ) return -1; int white = GetColor( 255, 255, 255 ); SetDrawScreen( DX_SCREEN_BACK ); while ( ProcessMessage( ) == 0 && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 ) { ClearDrawScreen( ); DrawBox( 0, 0, 240, 240, GetColor( 128, 0, 0 ), TRUE ); DrawFormatString( 0, 0, white, "TEST" ); ScreenFlip( ); } DxLib_End( ); return 0; }
Re: SetWindowSize関数を用いた結果 ( No.2 )
名前:南山まさかず 日時:2011/11/07 21:20

 いっちさん、ありがとうございます。バグか何かかと思ったら、 仕様だったのですね。勝手に騒いだようでどうも済みません。  最近GUIアプリケーションをほとんど作っていなかったので、 SetGraphMode関数の存在を忘れていました(汗)。  しかし、何故表面的なサイズと内部的なサイズがあるのでしょう か? 勉強不足の僕にとってはどちらかひとつに統一した方が分か りやすいと思うのですが……。それともWindowsの仕様なのでしょ うか? あくまで好奇心ですが、どなたか教えていただけるとあり がたいです。
Re: SetWindowSize関数を用いた結果 ( No.3 )
名前:管理人 日時:2011/11/27 21:12

すみません、前回お書き込みを見落としていました m(_ _;m > どちらかひとつに統一した方が分かりやすいと思うのですが……。 SetWindowSize は表示上のサイズ SetGraphMdoe はゲーム画面の解像度 をそれぞれ設定するための関数なので、統一することはできません・・・ ただ、SetWindowSize は普段は使う機会が無い関数なので( 大抵の場合 SetWindowSizeExtendRate で事足りるので )、 混乱を防ぐためにリファレンスには載せていません
Re: SetWindowSize関数を用いた結果 ( No.4 )
名前:南山まさかず 日時:2011/11/28 18:49

 管理人さん、ありがとうございます。わざわざ僕 の質問に答えていただいてい恐縮です。  最近VCを使用しているので、Dxライブラリの関数 を使うときにリファレンスを参照せずに、「多分こ んな感じの名前だよなぁ……」とか考えながら 「DxLib::」と打ち込んだらそれっぽい関数がずらっ と表示されるので、SetWindowSize関数と SetGraphMode関数をごっちゃにして覚えておりまし た……。どこかでIDEはプログラマをだめにするとか いうのを読んだことがありますが、僕に関しては本 当でした(汗)。  兎にも角にも、疑問に答えていただき本当にあり がとうございました。

Page: 1 |