DOBON.NETプログラミング道掲示板
(現在 過去ログ1 を表示中)

[ 最新記事及び返信フォームをトピックトップへ ]

■32932 / inTopicNo.1)  GDIりーく
  
□投稿者/ 野々村59 一般人(21回)-(2015/05/04(Mon) 12:34:22)
  • アイコン環境/言語:[C# 2010 NET3.5] 
    分類:[.NET] 

    2015/05/05(Tue) 11:41:12 編集(投稿者)

    [DllImport("Gdi32.dll", EntryPoint = "CreateRoundRectRgn")]
    private static extern IntPtr CreateRoundRectRgn
    (
    int nLeftRect, // x-coordinate of upper-left corner
    int nTopRect, // y-coordinate of upper-left corner
    int nRightRect, // x-coordinate of lower-right corner
    int nBottomRect, // y-coordinate of lower-right corner
    int nWidthEllipse, // height of ellipse
    int nHeightEllipse // width of ellipse
    );

    デバッグF5開始してから、この関数を8〜13回呼び出すと、
    必ずこのエラーが発生します。
    どうやらGDIリークと関係しているようですが、
    この関数を呼び出す回数が5回以下だとまずエラー発生しません。

    この関数を使用することを諦めるしかないでしょうか。
引用返信 削除キー/
■32933 / inTopicNo.2)  Re[1]: GDIりーく
□投稿者/ Azulean 大御所(443回)-(2015/05/04(Mon) 13:15:52)
  • アイコンNo32932に返信(野々村59さんの記事)
    > デバッグF5開始してから、この関数を8〜13回呼び出すと、
    > 必ずこのエラーが発生します。
    > どうやらGDIリークと関係しているようですが、
    > この関数を呼び出す回数が5回以下だとまずエラー発生しません。

    DllImport で定義している CreateRoundRectRgn とスクリーンショット中に出現している RoundedRegion の関係性が見えないのでコメントが難しいです。
    CreateRoundRectRgn で作成した HRGN(IntPtr) は不要になった時点で DeleteObject で消すことが必要になりますが、そのあたりは配慮できていますか?
引用返信 削除キー/
■32934 / inTopicNo.3)  Re[2]: GDIりーく
□投稿者/ 野々村59 一般人(22回)-(2015/05/04(Mon) 13:39:41)
  • アイコンご回答ありがとうございます。

    > DllImport で定義している CreateRoundRectRgn とスクリーンショット中に出現している RoundedRegion の関係性が見えないのでコメントが難しいです。

    private Region RoundedRegion(Button b)
    {
    return System.Drawing.Region.FromHrgn(CreateRoundRectRgn(0, 0, b.Width, b.Height, 15, 15));
    }

    でございます。失礼しました。

    > CreateRoundRectRgn で作成した HRGN(IntPtr) は不要になった時点で DeleteObject で消すことが必要になりますが、そのあたりは配慮できていますか?

    DeleteObject???とはなんでしょうか・・・
引用返信 削除キー/
■32935 / inTopicNo.4)  Re[3]: GDIりーく
□投稿者/ 野々村59 一般人(23回)-(2015/05/04(Mon) 13:43:01)
  • アイコンhttp://chokuto.ifdef.jp/urawaza/api/DeleteObject.html

    それっぽいのを見つけました、、
引用返信 削除キー/
■32936 / inTopicNo.5)  Re[4]: GDIりーく
□投稿者/ 野々村59 一般人(24回)-(2015/05/04(Mon) 13:48:17)
  • アイコン[System.Runtime.InteropServices.DllImport("gdi32.dll")]
    public static extern bool DeleteObject(IntPtr hObject);

    private Region RoundedRegion(Button b)
    {
    IntPtr ip = CreateRoundRectRgn(0, 0, b.Width, b.Height, 15, 15);
    Region region = System.Drawing.Region.FromHrgn(CreateRoundRectRgn(0, 0, b.Width, b.Height, 15, 15));
    DeleteObject(ip);
    return region;
    }

    foreach (Button b in buttons)
    {
    b.Region = RoundedRegion(b);
    }




    こんな感じにしましたが、
    まだ同じエラーが出ます。

    ただ、このエラーが出るまでに、その関数を呼び出した回数が少し増えました。
    17回くらいは呼び出せるようになりました。
引用返信 削除キー/
■32937 / inTopicNo.6)  Re[5]: GDIりーく
□投稿者/ Azulean 大御所(444回)-(2015/05/04(Mon) 18:13:35)
  • アイコンDeleteObject がなぜ必要だったかは理解できましたか?

    GDI オブジェクトは作った人が破棄(Delete)しないといけない、有限のリソースです。
    作って放置すると、いずれ限界を迎えますので、必要がなくなったら破棄、DeleteObject を呼ばないといけないのです。

    これは .NET の Region クラスでも同じことが言えて、IDisposable を実装しているクラスになりますので、不要になったら Dispose を呼ばないといけません。
    IDisposable について勉強していただいた方が良いでしょう。

    不要になるタイミングはきちんと考えてください。
    (きちんと考えずに適当な箇所にコードを入れると、おそらく別の例外が発生します)
引用返信 削除キー/
■32938 / inTopicNo.7)  Re[6]: GDIりーく
□投稿者/ 野々村59 一般人(25回)-(2015/05/05(Tue) 10:22:27)
  • アイコン
    > IDisposable について勉強していただいた方が良いでしょう。

    http://zecl.hatenablog.com/entry/20080226/p2

    アドバイスありがとうございます。
    勉強します。
引用返信 削除キー/
■32939 / inTopicNo.8)  Re[7]: GDIりーく
□投稿者/ 野々村59 一般人(27回)-(2015/05/05(Tue) 17:08:35)
  • アイコン2015/05/05(Tue) 17:12:03 編集(投稿者)

    下記最小コードでですね、
    ボタンの上にマウスカーソルを持って行くと、
    マウスカーソルをそこでじっとさせていても、
    コンソールの出力ウィンドウが大変なことになってる!!!!!!!!!!


    namespace WindowsFormsApplication1
    {
    public partial class Form1 : Form
    {
    public Form1()
    {
    InitializeComponent();
    }

    [DllImport("Gdi32.dll", EntryPoint = "CreateRoundRectRgn")]
    private static extern IntPtr CreateRoundRectRgn
    (
    int nLeftRect, // x-coordinate of upper-left corner
    int nTopRect, // y-coordinate of upper-left corner
    int nRightRect, // x-coordinate of lower-right corner
    int nBottomRect, // y-coordinate of lower-right corner
    int nWidthEllipse, // height of ellipse
    int nHeightEllipse // width of ellipse
    );

    int i = 0;
    private void button1_MouseMove(object sender, MouseEventArgs e)
    {
    IntPtr ip = CreateRoundRectRgn(0, 0, button1.Width, button1.Height, 15, 15);
    Region region = System.Drawing.Region.FromHrgn(ip);
    button1.Region = region;
    Console.WriteLine("i = " + i.ToString() + ", MouseX = " + e.X + ", MouseY = " + e.Y+" ←動いてないんだけどなぁ・・・");
    i++;
    }
    }
    }

引用返信 削除キー/
■32940 / inTopicNo.9)  Re[8]: GDIりーく
□投稿者/ Azulean 大御所(445回)-(2015/05/05(Tue) 22:45:16)
  • アイコン2015/05/05(Tue) 22:48:52 編集(投稿者)

    No32939に返信(野々村59さんの記事)
    > 下記最小コードでですね、
    > ボタンの上にマウスカーソルを持って行くと、
    > マウスカーソルをそこでじっとさせていても、
    > コンソールの出力ウィンドウが大変なことになってる!!!!!!!!!!

    MouseMove はマウスカーソル移動があったことを**保障しません**。
    何らかの事情により、同一座標で通知が来ることは十分にあり得ますので、それで困るような設計・実装をしないことです。

    (参考)
    Why do I get spurious WM_MOUSEMOVE messages?
    http://blogs.msdn.com/b/oldnewthing/archive/2003/10/01/55108.aspx

    余談
    ・このコード、結局、HRGN や Region の破棄漏れしまくりなんですが、意図的という認識ですよね?
    ・驚きのあまり書き込まれたのかもしれませんが、質問はきちんと質問とわかるようにしましょう。今の書き込みは、単に観測した事実を書き込んでいるだけに見えるためです。
引用返信 削除キー/
■32941 / inTopicNo.10)  Re[9]: GDIりーく
□投稿者/ 野々村59 一般人(28回)-(2015/05/06(Wed) 00:19:44)
  • アイコン> MouseMove はマウスカーソル移動があったことを**保障しません**。
    > 何らかの事情により、同一座標で通知が来ることは十分にあり得ますので、それで困るような設計・実装をしないことです。
    >
    > (参考)
    > Why do I get spurious WM_MOUSEMOVE messages?
    > http://blogs.msdn.com/b/oldnewthing/archive/2003/10/01/55108.aspx
    >
    > 余談
    > ・このコード、結局、HRGN や Region の破棄漏れしまくりなんですが、意図的という認識ですよね?
    > ・驚きのあまり書き込まれたのかもしれませんが、質問はきちんと質問とわかるようにしましょう。今の書き込みは、単に観測した事実を書き込んでいるだけに見えるためです。


    コメントありがとうございます。
    なるほど、保障してくれないのですね・・

    破棄についてしっかり学習してからまた取り組みたいと思います。
    一旦解決済みとさせていただきます。

    ありがとうございました。
解決み!
引用返信 削除キー/



トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

Mode/  Pass/


- Child Tree -