質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Visual Studio 2010

Microsoft Visual Studio 2010はMicrosoftが提供している統合開発環境(IDE)です。

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

Q&A

解決済

2回答

1330閲覧

図形内の色の塗りつぶし処理について

mery

総合スコア27

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Visual Studio 2010

Microsoft Visual Studio 2010はMicrosoftが提供している統合開発環境(IDE)です。

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

0グッド

1クリップ

投稿2018/12/14 12:18

前提・実現したいこと

クライアント領域内に円や四角形など、線で囲まれている領域が描かれている場合に、その領域内でマウスをクリックすると領域内が指定した色で塗りつぶされるようにするにはどうすればいいですか?

補足情報(FW/ツールのバージョンなど)

Microsoft Visual C++ 2010 Express C言語
WIN32 ユニコードビルド

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tiitoi

2018/12/14 14:06

線で囲まれている領域内の色は同じ色でしょうか? 例えば、Windows のペイントの塗りつぶしである箇所をクリックすると、そこと色が同じ部分が塗りつぶされますが、そのようなイメージであっていますか?
Zuishin

2018/12/14 23:45 編集

線の色を境界として塗りつぶすならそのようなアルゴリズムがあります。 そうでない場合、円と四角形なら非常に簡単です。多角形は少し高度になります。曲線だとかなり高度になります。 塗りつぶしたものを後で動かしたり大きさの変更をしたいということであれば、.NET を使って Windows Forms または WPF のコントロールを作るのがいいと思います。Windows Forms の場合、形は Region プロパティで設定します。
mery

2018/12/15 05:06

回答ありがとうございます。 線で囲まれている領域内の色は全部白で、線の色は黒で描かれています。
mery

2018/12/15 12:30

参考になるサイトを教えて頂きありがとうございました。 これらのサイトでは配列が使われていますが、クライアント領域内のデータを一度配列に保存しなければいけないのでしょうか? そこらへんのやり方が全然わからないので、教えてください。
Zuishin

2018/12/15 12:40

配列でなくても可能です。GetPixel, SetPixel を使えば x, y 座標でピクセルの取得・設定ができますから、二次元配列データの取得・設定の代わりにこれを使ってください。
Zuishin

2018/12/15 12:43

しかし正直、このようなマウスや画像を使った処理に C 言語を使いたくありません。面倒なので。C 言語でなければならない理由がなければ C# をお勧めします。
mery

2018/12/16 06:09

回答ありがとうございます。 紹介されたサイトの一番下のリンク先を参考に簡単なプログラムを作り試してみたのですがうまくいきません。 下のプログラムを実行して円を塗りつぶしてみたところ、途中で「スタックオーバーフロー」というエラーが発生してプログラムが止まってしまいます。また、塗りつぶす速度がすごく遅いです。 エラーが出ないようにするにはどうすればいいのでしょうか? void paint(HDC hdc,LONG x,LONG y){ if(GetPixel(hdc,x,y)==RGB(0,0,0)) return; SetPixel(hdc,x,y,RGB(0,0,0)); paint(hdc,x+1,y); paint(hdc,x-1,y); paint(hdc,x,y+1);   paint(hdc,x,y-1); } LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { HDC hdc; PAINTSTRUCT ps; switch (msg) { case WM_RBUTTONDOWN: hdc=GetDC(hWnd); paint(hdc,LOWORD(lp),HIWORD(lp)); ReleaseDC(hWnd,hdc); break; case WM_DESTROY: PostQuitMessage(0); break; case WM_PAINT: hdc=BeginPaint(hWnd,&ps); Ellipse(hdc,100,100,400,400); EndPaint(hWnd,&ps); return 0; default: return (DefWindowProc(hWnd, msg, wp, lp)); } return 0; }
Zuishin

2018/12/16 08:11

再帰を使っているので塗りつぶす面積が広いとスタックがあふれます。 ループに直せばそこは直ると思いますが、スピードが遅いとなると、GetPixel を使うのをやめて画像を一度配列に直してから処理し、それを一気に書き込むか、DirectX などを使う必要があるかもしれません。 チューニングは手間なので私はできません。実際に処理する画像を質問に追記して具体的にどの程度の規模なのかを明らかにし、ほかの方に尋ねてください。
Zuishin

2018/12/16 08:12

また、前にも言いましたが、円や四角であればもっと簡単に塗りつぶすことができます。塗りつぶす前の画像の作成方法も併せて追記すると解決が早いかもしれません。
guest

回答2

0

ベストアンサー

線で囲まれている領域内の色は全部白で、線の色は黒で描かれています。

で、あれば ExtFloodFill で達成できますね。

黒い枠線まで塗りつぶすのであれば

C++

1LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) 2{ 3 HDC hdc; 4 switch (msg) { 5 case WM_RBUTTONDOWN: 6 hdc = GetDC(hWnd); 7 SelectObject(hdc, GetStockObject(BLACK_BRUSH)); 8 ExtFloodFill(hdc, LOWORD(lp), HIWORD(lp), RGB(0x00, 0x00, 0x00), FLOODFILLBORDER); 9 ReleaseDC(hWnd,hdc); 10 break;

白い領域を塗りつぶすのであれば

C++

1LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) 2{ 3 HDC hdc; 4 switch (msg) { 5 case WM_RBUTTONDOWN: 6 hdc = GetDC(hWnd); 7 SelectObject(hdc, GetStockObject(BLACK_BRUSH)); 8 ExtFloodFill(hdc, LOWORD(lp), HIWORD(lp), RGB(0xff, 0xff, 0xff), FLOODFILLSURFACE); 9 ReleaseDC(hWnd,hdc); 10 break;

投稿2018/12/17 04:56

atata0319

総合スコア881

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mery

2018/12/17 10:20

回答ありがとうございました。こんな便利な関数があったとは全然知りませんでした。
guest

0

正直win32APIなんて最近触ってないので関数名やコードは提示できませんが、
こんな流れで行けるのでは。

// 矩形(線)の座標 int x, y, width, height; int onpaint = 0; // 内側を埋めるか ウィンドウプロシージャ マウスがクリックされた時 座標にかぶっているか(if) onpaint = 1; return DefWindowProc(); // こんなだったはず(適当) ペイント時 // ペイントのイベント switchで分岐 矩形(線)を書く if( onpaint == 1 ){ 矩形で埋める( x + 1, y + 1, width - 2, height - 2 ); }

スパゲッティなのはご了承を。

投稿2018/12/14 23:33

yukkuri

総合スコア624

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mery

2018/12/15 05:25

回答ありがとうございます。 「マウスがクリックされた時座標にかぶっているか」というのは具体的にはどういうことなんでしょうか?
yukkuri

2018/12/15 05:46

if( マウスのX取得() > x || マウスのX取得 < x + width )みたいな感じです。 わかりにくくてすいません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問