プロが教えるわが家の防犯対策術!

Visual C++ 2008で、イメージファイルの多分割アプリを作成しようとしています。
イメージファイルを、表示した上に色反転した破線を描画したいのですが、良い方法は無いでしょうか。色反転直線なら、DrawReversibleLine 。色反転破線四角なら、DrawReversibleFrame で書けるのですが、色反転した破線の直線の書き方がわかりません。
どなたか、ご教授頂けないでしょうか。

A 回答 (5件)

WinAPIを使って描画する方法でしょう



void myRevrseLine(HWND hWnd, POINT p1, POINT p2, COLORREF cl)
{
  HDC hDC = NULL;
  HPEN hPen = NULL;
  HGDIOBJ hOld = NULL;
  // DCの取得
  hDC = GetDC(hWnd);
  if (NULL != hDC) {
    // PENの生成
    hPen = CreatePen(PS_DOT, 1, cl);
    if (NULL != hPen){
      // PENの選択
      hOld = SelectObject(hDC, hPen);
      // 描画モードの変更
      SetROP2(hDC, R2_NOTXORPEN);
      // 始点へ移動
      MoveToEx(hDC, p1.x, p1.y, NULL);
      // 終点まで描画
      LineTo(hDC, p2.x, p2.y);
      // PENの後始末
      SelectObject(hDC,hOld);
      DeleteObject(hPen);
    }
    // DCの後始末
    ReleaseDC(hWnd, hDC);
  }
}
といった関数を準備します

この関数を置くファイルの冒頭に
#include <windows.h>
を記述します

呼び出しは
HWND hWnd = (HWND)this->Handle->ToPointer();
POINT p1, p2;
COLORREF cl;
// p1、p2の座標はクライアント座標
p1.x = 32;
p1.y = 32;
p2.x = 128;
p2.y = 128;
cl = RGB(255, 0,0);
myReverseLine(hWnd, p1, p2, cl);
といった具合で行います
    • good
    • 0
この回答へのお礼

ありがとうございます。
WinAPIは、敷居が高くて、なかなか使えていないです。
教えて頂いた方法で、ソースに追加してみましたが、何やらリンクエラーがいっぱい出て、ビルドが完了しません。当方のプロジェクトがCLR Windowsフォーム アプリケーションになっているためだと推測しますが、今ひとつ理解できていません。もう少し、WinAPIの使い方調べてみます。
ありがとうございました。

お礼日時:2012/03/07 14:41

Bitmapに対してとなるとそのままでは デバイスコンテキストを取得できないので


Graphicsオブジェクトを使うことになりそうです

// bmp というBitmapを使うならば
Graphics^ g = Graphics::FromImage(bmp);
HDC hdc = (HDC)g->GetHdc().ToPpointer();
myReviceLineDC(hDC, p1, p2, cl);
g->ReleaseHdc();
delete g;
といった具合に デバイスコンテキストを取得して

myReverseLineを改変して

void myReverseLineDC(HDC hDC, POINT p1, POINT p2, COLORREF cl)
{
  HPEN hPen = NULL;
  HGDIOBJ hOld = NULL;
  // PENの生成
  hPen = CreatePen(PS_DOT, 1, cl);
  if (NULL != hPen){
    // PENの選択
    hOld = SelectObject(hDC, hPen);
    // 描画モードの変更
    SetROP2(hDC, R2_NOTXORPEN);
    // 始点へ移動
    MoveToEx(hDC, p1.x, p1.y, NULL);
    // 終点まで描画
    LineTo(hDC, p2.x, p2.y);
    // PENの後始末
    SelectObject(hDC,hOld);
    DeleteObject(hPen);
  }
}

void myRevrseLine(HWND hWnd, POINT p1, POINT p2, COLORREF cl)
{
  HDC hDC = NULL;
  // DCの取得
  hDC = GetDC(hWnd);
  if ( hDC != NULL ) {
    myReverseLineDC(hDC, p1, p2, cl);
    ReleaseDC(hWnd, hDC);
  }
}

といった具合になるかと …
    • good
    • 0
この回答へのお礼

何度も回答して頂いて、ありがとうございます。
教えて頂いた方法で、下記のようにしてみました。
Bitmapには、描画できているのですが、色反転していないようです。
SetROP2やLineTo等もう少し勉強します。
ありがとうございました。

private: Bitmap^srcImage;
private: System::Void Form1_DragDrop(System::Object^ sender, System::Windows::Forms::DragEventArgs^ e) {
  array<String^>^ files = dynamic_cast<array<String^>^>(e->Data->GetData( DataFormats::FileDrop ));
  String^ fileOrFolder = files[0];
  FileInfo^ fli = gcnew FileInfo(fileOrFolder);
  String^ fullPath = "";
  if (fli->Exists) {
    fullPath = Path::GetDirectoryName(fileOrFolder);
    srcImage = gcnew Bitmap(fileOrFolder);
    this->pictureBox1->Image = srcImage;
  }
}
private: System::Void pictureBox1_Click(System::Object^ sender, System::EventArgs^ e) {
  if (this->srcImage) {
    Graphics^ g = Graphics::FromImage(this->srcImage);
    HDC hdc = (HDC)g->GetHdc().ToPointer();
    POINT p1, p2;
    COLORREF cl;
    // p1、p2の座標はクライアント座標
    p1.x = 0;
    p1.y = 0;
    p2.x = this->srcImage->Width - 1;
    p2.y = this->srcImage->Height - 1;
    cl = RGB(255, 0, 0);
    myReverseLineDC(hdc, p1, p2, cl);
    p1.y = this->srcImage->Height - 1;
    p2.y = 0;
    myReverseLineDC(hdc, p1, p2, cl);
    g->ReleaseHdc();
    g->Flush();
    delete g;
    this->pictureBox1->Refresh();
  }
}
private: void myReverseLine(HWND hWnd, POINT p1, POINT p2, COLORREF cl) {
  HDC hDC = NULL;
  HPEN hPen = NULL;
  HGDIOBJ hOld = NULL;
  // DCの取得
  hDC = GetDC(hWnd);
  if (NULL != hDC) {
    myReverseLineDC(hDC, p1, p2, cl);
    ReleaseDC(hWnd, hDC);
  }
}
private: void myReverseLineDC(HDC hDC, POINT p1, POINT p2, COLORREF cl) {
  HPEN hPen = NULL;
  HGDIOBJ hOld = NULL;
  // PENの生成
  hPen = CreatePen(PS_DOT, 1, cl);
  if (NULL != hPen){
    // PENの選択
    hOld = SelectObject(hDC, hPen);
    // 描画モードの変更
    SetROP2(hDC, R2_NOTXORPEN);
    // 始点へ移動
    MoveToEx(hDC, p1.x, p1.y, NULL);
    // 終点まで描画
    LineTo(hDC, p2.x, p2.y);
    // PENの後始末
    SelectObject(hDC,hOld);
    DeleteObject(hPen);
  }
}

お礼日時:2012/03/14 14:23

No3は間違いです



HWND hWnd = pictureBOx1->handle.ToPointer();
でした
    • good
    • 0
この回答へのお礼

ありがとうございました。
無事に、pictureBox に反転破線を描画することができました。
まだ勉強不足で理解できていないのですが、これはpictureBoxのようなコントロール・オブジェクトに対してのみ有効なのでしょうか。例えばビットマップオブジェクトに対して、描画する方法は、また別という事でしょうか。

お礼日時:2012/03/13 16:10

ピクチャーボックスに対してならば



PictureBox^ pict = (PictureBox^)sender;
HWND hWnd = (HWND)pict->Handle->ToPointer();

といった具合で ウィンドウハンドルをピクチャーボックスのものにしてあげましょう
    • good
    • 0

ゴメンなさい


gdi32.libとuser32.libの2個をリンカーに与えないといけませんでした

または
#pragma comment(lib,"gdi32")
#pragma comment(lib,"user32")
を記述してみましょう
    • good
    • 0
この回答へのお礼

ありがとうございます。
自分で理解するため、新規プロジェクト(CLRのWindows フォーム アプリケーション)を作成
し、Form1にpictureBoxのみ追加し、そのクリックイベントに、以下のコードにて試してみました。Form1の先頭には、教えて頂いた
#include <windows.h>
#pragma comment(lib,"gdi32")
#pragma comment(lib,"user32")
を追加することで、ビルドエラーはなくなりましたが、実行しpictureBoxをクリックしても
線が描画されません。いろいろ、自分なりに試したのですが、「#include <windows.h>
」で、「>C:\Program Files\Microsoft SDKs\Windows\v6.0A\include\objidl.h(5934) : error C2872: 'IDataObject' : あいまいなシンボルです。」が出てしまったりと、なかなか難しいです。もっとWinAPIの使用について、勉強が必要なようです。
ありがとうございました。

private: System::Void pictureBox1_Click(System::Object^ sender, System::EventArgs^ e) {
HWND hWnd = (HWND)this->Handle.ToPointer();
POINT p1, p2;
COLORREF cl;
// p1、p2の座標はクライアント座標
p1.x = 32;
p1.y = 32;
p2.x = 128;
p2.y = 128;
cl = RGB(255, 255, 255);
myReverseLine(hWnd, p1, p2, cl);
}

お礼日時:2012/03/11 18:52

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!