ホームページ  >  記事  >  バックエンド開発  >  C# GDI+ プログラミング (5)

C# GDI+ プログラミング (5)

高洛峰
高洛峰オリジナル
2016-12-17 10:09:471422ブラウズ

ウィンドウの非クライアント領域に描画するAPI関数を呼び出します

GDI+のGraphicsクラスにはFromHdc関数があり、この関数はウィンドウデバイスコンテキスト(DC)に基づいてGraphicsオブジェクトを作成できます。 vc++、ウィンドウのクライアント領域と非クライアント領域での描画 これは、GetWindowDC 関数と GetDC 関数の呼び出しが異なるだけです。前者はウィンドウ DC 全体を取得し、後者はウィンドウ クライアント領域 DC を取得します。

その後、C# で GetWindowDC 関数を呼び出してウィンドウ DC 全体を取得し、FromHdc を通じてそれを読み込むことで、ウィンドウ全体を描画できるようになります。

C# で WINDOWS API を呼び出す方法、またはダイナミック リンク ライブラリ (DLL) の関数を呼び出す方法。

VC++ と同様に、最初にダイナミック リンク ライブラリをインポートしてから、次のように API 関数を宣言します:

[System.Runtime.InteropServices.DllImport("User32.dll")]
private static extern IntPtr GetWindowDC(IntPtr hwnd) );

もちろん、上記は最も単純であり、まだ説明していない詳細がいくつかありますが、基本的に使用できるようにするだけにしておきます。詳細は後ほど。

C# では、VC++ では HDC と HWND を処理するなど、API 関数のパラメーターの型が異なることがわかります。ここで宣言するときは、代わりに IntPtr が使用されました。C# にはポインターの概念がないため、これを行う方法はありません。HDC と HWND の型定義を確認したところ、両方ともポインター型であることがわかりました。

そのため、C# では、領域ハンドル HRGN、HICON アイコン、HFONT フォント ハンドルなどを含む、これらの「ハンドル」型は IntPtr に置き換えられます。

例を見てみましょう(前の章からの続き)

パブリック部分クラス Form1: Form
{
//ダイナミック リンク ライブラリをインポートし、関数を宣言します。この関数は Form1 クラスで宣言されます。
[System.runtime.interopservices.dllimport( "user32.dll")]
path = new graphicspath();
/ / load png pictures t bitmap bmp = new bitmap( "d:\ image \ win.png");
public form1 () {
InitializedComponent (); 領域 i for (int y = 0; y & lt; bmp.head; y ++)
for (int x = 0; x & lt; bmp.width; x + +) {
COLOR COR = BMP.Getpixel (x, y); B int argb = cor.toargb ();
Byte [] Bargb = Bitconverter.getBytes (ARGB); // ピクセルのカラー値は透明ではありません
if (bargb [3]! = 0) {
// これこれこれ ピクセル領域をパスに追加します
//ウィンドウ表示領域を設定し、パスを介してリージョンを作成します
This.Region = new Region( PATH); i this.paint+= formpaint;
}}
Private void Formpaint (Object SENDER, PAINTEVENTARGS E) {


OnPaintBackground (E)
// ハンドルは、Intptr 型です
intptr HDC = GetWindowDC; this.Handle); new Rectangle(0, 0, bmp.Width , bmp.Height));
}
inpaintbackground(Painteventargs e)を保護しますこの効果を達成するには、何らかの問題が発生するか、多くのトラブルが発生する可能性があります。ただ解決していないだけです。ウィンドウ全体を完全に更新せずにウィンドウを移動したり最大化すると、この問題が発生します。この問題は後で解決します

興味のある友達もこの問題を解決できます。

また、ウィンドウのクライアント領域のみを透明なブラシを使用して塗りつぶします。ウィンドウ全体(タイトルバーを含む)を塗りつぶしたい場合は、ウィンドウ全体に描画する場合と同じ方法で取得します。 WindowDC を作成し、

Graphics オブジェクトを作成してウィンドウの背景を描画します。

(余談: vc++ では、クライアント領域と非クライアント領域には、WM_PAINT と WM_NCPAINT という異なる再描画メッセージがあります。これには注意してください。非クライアント領域を更新するときは、クライアント領域は再描画されませんが、再描画しないでください。何か問題が発生しても、効率に影響するのは常に悪いことです。できれば避けてください)

自己描画ウィンドウの非クライアント領域(タイトルバー、最大化、最小化、閉じるボタンを含む)

メッセージ処理を書き換えます関数wndproc

パブリックパートクラスフォーム1:form form)

messagebox.show( "タイトルバーをダブルクリックしました")。デフォルトでは。

メッセージに対応する値を確認するには、たとえば、WM_LBUTTONDOWN をマークし、右クリックして [定義に移動] を選択して表示します。

m.HWnd にはウィンドウハンドルが格納されます。m.LParam と m.WParam は、CreateWindow 関数の WPARAM パラメーターと LPARAM パラメーターの説明を参照してください。

非クライアント領域を自分でペイントする作業は本当に多すぎます。ここでは一般的なアイデアと方向性のみを説明します。時間があるときにもう一度実行します。

もちろん、ウィンドウに枠があるかどうかなどのさまざまなデータを計算することが前提です。枠がある場合は、枠の幅と高さを取得し、4つの枠の長方形の面積を計算します。

最後に、ウィンドウに最大属性と最小属性があるかどうかを判断し、3 つのボタンの領域を取得します。

これらのデータは SystemInformation クラスに保存されます。たとえば、SystemInformation.CaptionButtonSize はタイトル バー ボタンのサイズを保存します。これらの 3 つのボタンは

であるため、ボタンの領域を決定できます。境界線の高さと幅を除くすべて。

SystemInformation.CaptionHeight にはタイトル バーの高さが格納され、枠線の高さと幅は SystemInformation.BorderSize または SystemInformation.Border3DSize に格納されます。これらはウィンドウの FormBorderStyle に従って決定されます。 MaximizeBox でウィンドウを最大化するかどうかを決定できます。True の場合は最大化されます。

上記のデータを取得した後、マウスの左ボタンのメッセージ WM_NCLBUTTONDOWN や WM_NCLBUTTONUP など、非クライアント領域のさまざまなメッセージに応答します。

マウスでWM_NCMOUSEMOVEというメッセージを移動すると、自己描画が始まります。

Rectangle クラスの Contains 関数は、点が長方形の領域内にあるかどうかを判断できます。

C# GDI+ プログラミング (5) 関連記事の詳細については、PHP 中国語 Web サイトに注目してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。