none
GetSystemMetrics( SM_MOUSEPRESENT ) の使い方。 RRS feed

  • 質問

  • 超初心者で申し訳ないのですが、

    BOOL GetSystemMetrics( SM_MOUSEPRESENT );

    の結果を、『MessageBox』で表示されて結果を見たいのですが、

    MessageBox( xxx );

    どの様に記述すればよいのでしょうか???

     

    2010年5月24日 13:33

回答

  • 事の発端は質問主が

    BOOL GetSystemMetrics( SM_MOUSEPRESENT );

    と書いてしまったためでしょうが、質問主はこの宣言をプログラム中には書いていないでしょう。

    なぜなら、通常Windowsでプログラミングしている状況ではすでに定義されているから。

    そして、SM_MOUSEPRESENTの結果を扱う場合にはBOOLが正しいです。

    なぜなら、MSDNには0以外(TRUE)または0(FALSE)が返ると明記してあります。

    よって、

    BOOL bRet = (BOOL)GetSystemMetrics( SM_MOUSEPRESENT );

    if(bRet) printf("TRUE");

    else printf("FALSE");

    となります。

    気をつけなければならないのは、TRUEは0以外だと言うことです。戻り値をTRUEと比較してはいけません。

    もし、MSがこの仕様を変更して機能を拡張する場合、0以外の数値の種類が増えるでしょう。そのときでも、0(FALSE)か0(FALSE)でないかを比較してさえいればプログラムの修正は不要です(拡張された機能を使えるかどうかは別として)。

    #最近、文末にwを多用する人がいますが、wは口を尖らせた様子を表します。私はそのように解釈します。

     

    • 編集済み bussaba 2010年5月27日 9:46 誤記訂正
    • 回答としてマーク s_takejp 2010年6月6日 5:07
    2010年5月27日 9:45

すべての返信

  • BOOL GetSystemMetrics( SM_MOUSEPRESENT );
    の結果を、『MessageBox』で表示されて結果を見たいのですが、
    MessageBox( xxx );
    どの様に記述すればよいのでしょうか???

    文字列に変換してください。
    char[] なり、wchar_t[] なり、TCHAR[] なり、std::string なり、std::wstring なり、CString なり、作成しているプロジェクトの種類に合わせて選んでください。

    厳しいことを言うようですが、この方法については「超初心者なので教えてください」と聞くよりはご自身で調べて、理解して頂きたいと思います。
    下手に鵜呑みにすると、バッファオーバーランなどの脆弱性を埋め込むことになりかねません。


    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
    • 回答の候補に設定 山本春海 2010年6月2日 7:40
    2010年5月24日 14:30
    モデレータ
  • 些細なことですが、すごく重要なので。。。

    GetSystemMetrics API は引数に何を与えるか?にかかわりなく

    int WINAPI GetSystemMetrics( int index );

    という定義になっています。戻り値は、BOOL ではありません。


    わんくま同盟,Microsoft MVP for Visual C++(Oct 2005-) http://blogs.wankuma.com/tocchann/
    2010年5月24日 16:25
  • 面倒なのでANSI限定でw

    int b = ::GetSystemMetrics( SM_MOUSEPRESENT );
    ::MessageBoxA( NULL, b ? "True" : "False" , "MOUSEPRESENT" , 0 );

    この記述はバッファオーバーランとは無縁なはずです。(褒められたものではない点がいくつか存在しますがw)

     

    >とっちゃんさん

    結果的には、ではありますが WinDef.hを使う環境なら

    typedef int                  BOOL;

    で、最終的な内部的挙動は同じにはなりますよね?w (あくまで褒められた論点ではないですがw)

     

    ただ、それよりもとても気になったことが2点あります。

     

    GetSystemMetrics 関数 より

     

    <<<SM_MOUSEPRESENT>>>

    マウスが接続されているかどうかを示す値を取得します。接続されている場合は 0 以外の値(TRUE)が、接続されていない場合は 0(FALSE)が返ります。

     

     

    戻り値

    関数が成功すると、要求した値または現在の構成が返ります。

    関数が失敗すると、0 が返ります。GetLastError 関数は、拡張エラー情報を提供しません。

     

     

     

    あれ~っ?って感じです。

    これでは関数が失敗したかどうかは区別できない気がしますが、そんなことよりもっと重大なことが・・・w

     

    PRB: ISMOUSE 関数を常に返します。Windows 95 および 98 で作成されます。

     

    機械翻訳がやっぱり素敵な日本語になっちゃってるので英語版の方が分かりやすいかもしれませんがw

    私が先ほどから数回XPで確認したところ、今のところマウスを付けても外してもTRUEしか返ってきませんw

    (GDIのなんかの件もあったからXPは98的に動いてる部分がいくらかあったりするのかな?)

     

    ・これは仕様によるものです。

     

    とすると、どのように回避されますか?マウスがコンピューターから切断された場合でも、T.。

    #別の方法で確認出来ればそれで問題ないでしょうがw

    2010年5月24日 17:53
  • 結果的には、ではありますが WinDef.hを使う環境なら

    typedef int                  BOOL;

    で、最終的な内部的挙動は同じにはなりますよね?w (あくまで褒められた論点ではないですがw)

    結果的に同じならというのは非常に危険です。

    BOOLはたまたま内容に変更がなかっただけです。

    WPARAM や LPARAM はプラットフォームによって実際のプリミティブな型が異なります。ポインタも変わりますよね。

    なので、たまたま同じだからと言って、あたかも問題がないかのような表現は、不特定多数の人が見るところへの回答としては最も好ましくないものといえます。

    回答する側に立つのであれば、見られているということを強く意識して発言することをお勧めしますよ。

    常に誰かがフォローしてくれるわけではないですし、自分の言葉くらいは責任が持てる程度の発言をすることを心がけるべきです。それがたとえ100年後に参照されるようなことであったとしても。です。

     


    わんくま同盟,Microsoft MVP for Visual C++(Oct 2005-) http://blogs.wankuma.com/tocchann/
    2010年5月25日 2:53
  • >WinDef.hを使う環境なら

    >で、最終的な内部的挙動は同じにはなりますよね?w

    と書いてるだけなので、問題ないとは書いていませんし、もちろん大きく仕様変更があるとダメですが、そんなところまで100年先でも「責任」を持とうとするならば、自分がコンパイラ作ってるわけじゃない限り、もしかするとあらゆる記述は回答不可能ではないでしょうか?w

    回答というよりは下の2点を知りたかったので、この場に投稿させていただいた次第です。

     

    もしも「超初心者」というのが「謙遜」である可能性があった、ならば

    その際質問文の

     

    >BOOL GetSystemMetrics( SM_MOUSEPRESENT );

     

    という表現をみる限り、これはSM_MOUSEPRESENTにおける

    TRUEかFALSEが返る、ということを、知らない場合に調べなくてもだいたい分かるようにするための「配慮」で

     

    int GetSystemMetrics(
      int nIndex   // システムメトリックまたは現在の構成
    );

     

    という定義を知っていながら、そう表現されている、という可能性も、なくはないのではないか?と、思っただけですよ♪

    (違うかもしれませんがw)

     

    もちろん、intが戻り値なんだからintに格納するのが良いかもしれませんが、ソースの読みやすさを取るなら(そして、そういう「念のため」のこともするなら)

     

    BOOL b=(BOOL)GetSystemMetrics( SM_MOUSEPRESENT );

     

    くらいの方がいいかもしれない、かな?と思います。

     

    ・・・・まぁ、結果的に有益な情報が集まる可能性があるならば、質問者と回答者(というより、スレッドを立てた方以外の方)の間に(投稿のための条件というか、が)そんなに差異がない方が好ましいのではないでしょうか?

     

    で、下の2点については対処法をご存知でしょうか?w (重要w)

    特に一番下の問題について回避法が存在しないとなると、そもそもGetSystemMetrics( SM_MOUSEPRESENT )がつかえる状況は限定される はずです。(超重要、かもw)

    2010年5月25日 13:20
  • と書いてるだけなので、問題ないとは書いていませんし、もちろん大きく仕様変更があるとダメですが、そんなところまで100年先でも「責任」を持とうとするならば、自分がコンパイラ作ってるわけじゃない限り、もしかするとあらゆる記述は回答不可能ではないでしょうか?w

    「結果的に同じになるかもしれないが、意味的には正しくない」など、明確に断っておけば良いとは思います。
    そういった断りがないと、鵜呑みにしてしまう危険性もありますよね?

    ・・・・まぁ、結果的に有益な情報が集まる可能性があるならば、質問者と回答者(というより、スレッドを立てた方以外の方)の間に(投稿のための条件というか、が)そんなに差異がない方が好ましいのではないでしょうか?

    回答というか、アドバイスを重ねていくのであれば、質問者が鵜呑みにして問題となる可能性のある発言はぜひとも控えて頂きたいと思います。
    質問者の置かれた状況や書いた内容によっては、そのまま受け取って実装し、後々被害を生むかもしれません。
    もちろん、自己責任ではありますが、回答の際に少し気を配ることでそういった悲劇は避けられるものですから。


    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
    2010年5月25日 14:46
    モデレータ
  • もし仮に、ですが

    「WinDef.hを使う環境なら」(つまり、typedef int BOOL;の現状では)という前提がある ので、「これを踏まえて」今のところは鵜呑みにしても問題は発生しないのではないでしょうか?

    鵜呑みというよりはtypedefの性質としての事実です。

     

    また、今のところはそうなっているために、最終的にコンパイルされる段階になるとどちらも「サイズがintと同じ符号付き整数型」として扱われるかたちにしかならないため、そういうディープな挙動の意味では同じ、という事も含んで書いたつもりでした。

     

    これらを踏まえないで 「intのかわりにBOOLを使っても最終的な内部的挙動は同じにはなる」 というところだけを見て鵜呑みにしたときに、しかも将来typedef int BOOL;ではなくなった時に
    初めてまずいかもしれない、ということになります。 そういうことならば、確かにそうだと思います。

     

    ただ、これは元々GetSystemMetrics( SM_MOUSEPRESENT )限定 での話なので、TRUEかFALSE(0)か、失敗時に0が返る、というのは記述をみる限り確かです。

    つまり、 BOOL が int より小さいサイズになったり整数じゃない謎の型になったりするか

    GetSystemMetricsの戻り値自体が変わる、という事が起きて、しかもなおかつそれによってコンパイルエラーになったり警告が大量に出るとか

    が起きて、初めて問題がある、ということになるはずです。

     

    しかし

    1.そこまで重要なビジネス的な場面とはどうも思えない

    2.もし万が一そういう場面の方が(しかもGetSystemMetricsを知らないときに)裏事情とか知らずに見たとしても、重要だったら通常は流れから自分でも意味を確認したりするはず・・・!

    3. そういう大規模な仕様変更があるならもっと他の部分で色々と直さないといけない可能性が高いのでは?

    とは感じました。

     

    「WinDef.hを使う環境なら」(つまり、typedef int BOOL;の現状では)という前提 の時点で、私としては「状況を絞った」のでそこそこは気を配ったつもりでしたが、少し伝わりづらい可能性があった、のは確かかもしれませんねw

     

    ただ、上記投稿(の一部分)だけから鵜呑みにするという事があったら、それはそれで危険だと思います。ネット上には中途半端な情報を記述しているページが沢山あって、だけれどそれをみるから理解が促進される、という可能性があるから捨てがたい、という事は必ずあるはずです。

     

    単に、よく調べる習慣をつける、というのは最初の返信でAzuleanさんが仰っているように、私からも強くお勧めします。

     

    もちろん、戻り値がintになっている以上、intで受け取るのが(自分で再定義とかを除けば)最も変更可能性に強いであろう事から「言語としては」妥当とは思います。

     

    しかし何度も書きますが、私はこの問題ではまずそれよりも上記の私のレスの下の2点の疑問を重要だと考えます。(Azuleanさんもご存知ないですか?)

     

    なぜなら、ここ次第では 「 もし、一部分だけ鵜呑みにしたいなどと思っても、使う意味がない環境があるので、鵜呑みにすらしようがない 」 可能性があるためですw

    2010年5月25日 16:09
  • スレッドの本筋から大きく外れるので要点だけ。

    >何度も書きますが

    何度かいても構いません。

     

    それがこのスレッドで行うべき問題であると誰もが認識できるものであれば。

     

    このスレッドでは七空白さんは回答する側の立場、すなわち、生徒に質問を受けた先生と同じ立場にいます。残念ですが、便乗質問できる立場ではありません。

    それを踏まえた上で、このスレッドで行うべき話題だと思うのであれば、続ければいいと思います。

     


    わんくま同盟,Microsoft MVP for Visual C++(Oct 2005-) http://blogs.wankuma.com/tocchann/
    2010年5月25日 17:46
  • あれ?w ここってそんなに厳しい場所でしたっけ?

    と思って調べてみたところ・・・

     

    CLIでの、private による値の隠ぺいについて

     

    MSFT, モデレータ  鹿島幸則 [Yukinori Kashima] さんの2008年2月18日 9:13の投稿から一部引用させていただきます。

     

    フォーラムは”質問”に対して”回答”をもらうための場所として提供しているのではなく、”ディスカッション”や”コミュニケーション”を主体とした、意見交換の場所として提供しています。 そのため、基本的な書き込みのスタンスは、”私はこう思う” や ”私はこう考える” という事になります。

    つまり、”回答”と思える内容も、書き込んだ人の、”私はこう思うよ、こすうればよいのでは?” という内容が投稿されていると考えればわかり易いでしょう。 同じトピックであれば、もちろん便乗質問も OK ですし、間違えることもあります。

     

    私は以前この文章を読んだ記憶があったので

    「お~良い場所だな♪」と思ってたのですがw (こういう場所を提供していただけるというのはとてもありがたいですねw)

     

    このために別スレッド立てちゃうとなると情報が分散されてフォーラム的には逆に分かりにくくなってしまうのでは?

    と、強く意識はしないにしろ思ってたので、上記の点について、私はここで便乗質問させていただきましたw

     

    というわけで、問題なさそうだしここにまとめないと、そもそもGetSystemMetrics( SM_MOUSEPRESENT )が使えるかどうかが分からない のでは本末転倒だから

    引き続き募集ですw ご存知の方いらっしゃいましたらぜひ教えてください♪

    2010年5月25日 18:11
  • というわけで、問題なさそうだしここにまとめないと、そもそもGetSystemMetrics( SM_MOUSEPRESENT )が使えるかどうかが分からない のでは本末転倒だから
    引き続き募集ですw ご存知の方いらっしゃいましたらぜひ教えてください♪

    この件に関しては、元の質問者である s_takejp さんも困るであろう事象なので、便乗質問という形でもかまわないと思います。
    (この件は「それがこのスレッドで行うべき問題」と判断しています。元の質問者が望まないと予想される質問・情報交換を続けると、元の質問者から見れば邪魔に見えるかもしれないので、ケースバイケースです。)

     

    こちらを読めば、0 を返すことがほとんどないという認識をもてると思います。(失敗を考慮しない場合)
    http://msdn.microsoft.com/en-us/library/ms724385(VS.85).aspx

    リモートデスクトップ用の仮想マウス以外にも、何らかの仮想マウスが存在する可能性があるので、デバイス列挙から実体のマウスが接続されているかどうか調べるのも大変だとは思います。
    やりたいことが見えてないので、とりあえずこれ以上は何ともいいかねます。


    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
    2010年5月25日 22:31
    モデレータ
  • 成功と失敗の時の戻り値分岐に関しては、英語版のコミュニティコンテンツに書いてあるように、成否の判定には使えないことになります。
    http://msdn.microsoft.com/en-us/library/ms724385(VS.85).aspx

    なぜ Return Value の記述がああなっているかはわかりません。
    単なるミスかもしれませんし、特定の引数によってはそのように動作するのかもしれません。


    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
    2010年5月25日 22:40
    モデレータ
  • 私個人は、元質問者の s_takejp さんが聞きたかったのは、GetSystemMetrics のほうではなく、MessageBox に表示するために「何らかの数値情報を文字列にする方法」だったのではないか?と思っています。

    何かで、たまたま GetSystemMetrics を見つけたから試してみているという程度で、SM_MOUSEPRESENT の返す値ましてやGetSystemMetrics の成否は質問の本質部分には全く含まれていないんじゃないか?と思っています。あくまでも私が思ってるだけですが。

     

    さて、否定だけしていても仕方ないので、私が保持する古いドキュメントをあたってみました。

    Windows 3.1 SDK のヘルプと、Win32 API プログラマーズリファレンスの戻り値部分には

    関数が正常に終了した場合、戻り値は要求されたシステム メトリックを示します。

    と書かれていました。少なくとも古いドキュメントでは失敗はなかったということを意味しています。

    ただ、当時と今では、状況が異なりますので、もしかしたら今はエラーが発生することがあるのかもしれません。

    すごく古いドキュメントと今のものしかないので、何とも言えない部分はあるのですが、戻り値は、引数のところに書かれている情報ないしは、0という意味なんだと思います。 

    ちなみに、昔は本当に SM_MOUSEPRESENT が FALSE(接続されていない) を返すことがありました(USBがなかった時代の話なので現在でも該当するわけではありません)。

     


    わんくま同盟,Microsoft MVP for Visual C++(Oct 2005-) http://blogs.wankuma.com/tocchann/
    2010年5月26日 2:02
  • Azuleanさん、とっちゃんさん、わざわざありがとうございます。

    つまり、何でかは分からないけど

    説明の文章を読む限りは、一部の引数ではやはり確認しようがないか、一部の引数では記載内容が誤っているか、結果的にはこの場合、単なるミスで全面的にReturn Valueの記述が誤っているか、のいずれかになるはずだということですね。

    これが作られた当初はちゃんと動作するように作られていた、ということですか。

     

    ということは、現状ではうまくいかない場合があるのはやはり仕様で、それ自体の回避法は存在しないかも、ということですね?

     

    迷いましたが一応書きますと、なぜ私はGetSystemMetrics のほうがメインだと思ったのかというと、タイトルが

    "GetSystemMetrics( SM_MOUSEPRESENT )の使い方。"

    だったためですw

    裏があるかもしれない、と思って実際にやってみると、Trueしか返って来ないので、s_takejpさんが、これの「自分の」使い方が間違っているのでは?という疑念に駆られて投稿されたのでは?と、早々に推測してしまいましたがw

    確かに MessageBox がメインである可能性も否定はできないかもしれませんw

     

    流れ的にはこれだけで終わるのもあれかもなので、一応その場合の対処法の例として上記と同じようにANSI限定の場合でも。

    (そのままコンパイルはできません。概要だけです.)

    GetSystemMetricsの全てを確認してはいませんが GetSystemMetricsに限らず「intの数値」 を10進表示させる場合

     

    /* SIZE_はintを表示させる場合に必要な、終端文字を含んだ最大文字数以上の大きさとします(環境によってintのサイズが変わりますし、状況によっても最低限のサイズは変わります) */

    char c[SIZE_];

    int i=/*関数かなにか*/;

    if (~) /* 関数から取得で、戻り値チェック・その場合の処理が必要な場合はそれを行う */;

    if (sprintf_s(c,SIZE_,"%d" ,i)== /* */) /* 一応sprintf_s の戻り値チェックを行うならばここでなにかします */;

    MessageBoxA( NULL, c, "何か" , 0);

     

    など. sprintf_s については

    http://msdn.microsoft.com/ja-jp/library/ce3zzk1k%28VS.80%29.aspx

    のとおりです。

     

    #MessageBoxて、MFCのCWnd::MessageBoxの可能性もありますかね?w MessageBox::Showとは書かれていないので、.NETではない感じがしますが…w 推測ばかりでもきりがないので、これ以上の追及が必要でしたらs_takejpさん自身に再度ご登場いただくよりないかもしれませんw

    2010年5月26日 20:44
  • 事の発端は質問主が

    BOOL GetSystemMetrics( SM_MOUSEPRESENT );

    と書いてしまったためでしょうが、質問主はこの宣言をプログラム中には書いていないでしょう。

    なぜなら、通常Windowsでプログラミングしている状況ではすでに定義されているから。

    そして、SM_MOUSEPRESENTの結果を扱う場合にはBOOLが正しいです。

    なぜなら、MSDNには0以外(TRUE)または0(FALSE)が返ると明記してあります。

    よって、

    BOOL bRet = (BOOL)GetSystemMetrics( SM_MOUSEPRESENT );

    if(bRet) printf("TRUE");

    else printf("FALSE");

    となります。

    気をつけなければならないのは、TRUEは0以外だと言うことです。戻り値をTRUEと比較してはいけません。

    もし、MSがこの仕様を変更して機能を拡張する場合、0以外の数値の種類が増えるでしょう。そのときでも、0(FALSE)か0(FALSE)でないかを比較してさえいればプログラムの修正は不要です(拡張された機能を使えるかどうかは別として)。

    #最近、文末にwを多用する人がいますが、wは口を尖らせた様子を表します。私はそのように解釈します。

     

    • 編集済み bussaba 2010年5月27日 9:46 誤記訂正
    • 回答としてマーク s_takejp 2010年6月6日 5:07
    2010年5月27日 9:45
  • 最初に記載した様にC++を勉強し始めようとしている 【超初心者】 なので、ここまで議論していただけるとは思っておりませんでした。皆さんありがとうございます。

    先日までは、.NET と MFC の違いすら知らない状態でして、、、、

    MessageBox を利用し、何をいじれば何が起こるのかを検証することで理解を深めようと、色々なページを参照しながらやっとMessgaeBoxの利用方法が理解できた状況です。

    この程度なので、知りたかったのは下記程度でして、、、、

    > BOOL bRet = (BOOL)GetSystemMetrics( SM_MOUSEPRESENT );

    > if(bRet) printf("TRUE");

    > else printf("FALSE");

     

    お手数おかけして申し訳ありませんでした。。。

     

    2010年6月6日 5:20