2011年07月28日

Formを突き抜けてFormの後ろ側をクリックできるようにする

レイヤードウィンドウを使用してウィンドウの後ろにあるオブジェクトを操作出来るようにする。
レイヤードウィンドウを使用するのでウィンドウとして表示する画像ファイルを別途用意する。

WIN32APIを使うのでAPI宣言。
    [DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr CreateCompatibleDC(IntPtr hdc);

[DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);

[DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int DeleteObject(IntPtr hobject);

[DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int DeleteDC(IntPtr hdc);

[DllImport("user32")]
public static extern IntPtr GetDC(IntPtr hWnd);

[DllImport("user32")]
public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);

public const int AC_SRC_OVER = 0;
public const int AC_SRC_ALPHA = 1;
public const int ULW_ALPHA = 2;


[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct BLENDFUNCTION
{
public byte BlendOp;
public byte BlendFlags;
public byte SourceConstantAlpha;
public byte AlphaFormat;
}

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int UpdateLayeredWindow(
IntPtr hwnd,
IntPtr hdcDst,
[System.Runtime.InteropServices.In()]
ref Point pptDst,
[System.Runtime.InteropServices.In()]
ref Size psize,
IntPtr hdcSrc,
[System.Runtime.InteropServices.In()]
ref Point pptSrc,
int crKey,
[System.Runtime.InteropServices.In()]
ref BLENDFUNCTION pblend,
int dwFlags
);

フォームの CreateParams プロパティを override してレイヤードウィンドウにする。
フォームを突き抜けるには下記のWS_EX_TRANSPARENTをスタイルに設定するのがポイント。
    protected override CreateParams CreateParams
{
get
{
const int WS_EX_LAYERED = 0x00080000;
const int WS_EX_TRANSPARENT = 0x00000020;
const int WS_BORDER = 0x00800000;
const int WS_THICKFRAME = 0x00040000;

System.Windows.Forms.CreateParams cp = base.CreateParams;

cp.ExStyle = cp.ExStyle | WS_EX_LAYERED;
cp.ExStyle = cp.ExStyle | WS_EX_TRANSPARENT;
if (this.FormBorderStyle != FormBorderStyle.None) {
cp.Style = cp.Style & (~WS_BORDER);
cp.Style = cp.Style & (~WS_THICKFRAME);
}

return cp;
}
}

レイヤードウィンドウを設定するメソッドを定義。
BLENDFUNCTION構造体のSourceConstantAlphaの値で透明度を指定できるのでお好みで設定する。
    private void SetLayeredWindow(Bitmap bmp)
{
IntPtr screenDc = IntPtr.Zero;
IntPtr memDc = IntPtr.Zero;
IntPtr hbmp = IntPtr.Zero;
IntPtr oldbmp = IntPtr.Zero;

try {

screenDc = GetDC(IntPtr.Zero);
memDc = CreateCompatibleDC(screenDc);
hbmp = bmp.GetHbitmap(Color.FromArgb(0));
oldbmp = SelectObject(memDc, hbmp);

// イメージの透過情報を設定
BLENDFUNCTION bf = new BLENDFUNCTION();
bf.BlendOp = AC_SRC_OVER;
bf.BlendFlags = 0;
bf.SourceConstantAlpha = 128; // 50%の透過度でイメージを表示する!
bf.AlphaFormat = AC_SRC_ALPHA;

// ウィンドウ更新
this.Size = new Size(bmp.Width, bmp.Height);
Point pptDst = new Point(this.Left, this.Top);
Size psize = new Size(this.Width, this.Height);
Point pptSrc = new Point(0, 0);
User32.UpdateLayeredWindow(this.Handle, screenDc, ref pptDst, ref psize, memDc, ref pptSrc, 0, ref bf, ULW_ALPHA);

} finally {
if (screenDc != IntPtr.Zero) {
ReleaseDC(IntPtr.Zero, screenDc);
}
if (hbmp != IntPtr.Zero) {
SelectObject(memDc, oldbmp);
DeleteObject(hbmp);
}
if (memDc != IntPtr.Zero) {
DeleteDC(memDc);
}
}
}

あとはフォームのコンストラクタあたりでイメージファイルを読み込んで上記のメソッドを呼んであげる。
    public Form1()
{
Bitmap bmp = new Bitmap(@"C:\test.png");

Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
BitmapData bd = bmp.LockBits(rect, ImageLockMode.ReadOnly, bmp.PixelFormat);

Bitmap ret = new Bitmap(bd.Width, bd.Height, bd.Stride, PixelFormat.Format32bppArgb, bd.Scan0);

bmp.UnlockBits(bd);

SetLayeredWindow(bmp);
}


申し訳ないがここにのせたソース、動いてるソースを切って貼ったものではあるけれども、貼った後の検証をしてないのでコピペして動かなかった場合、各自アドリブでの対応をお願いしたい。
posted by なまい at 20:45| Comment(0) | C# | このブログの読者になる | 更新情報をチェックする

2011年06月25日

フォームをアクティブにせずに開く

フォームを非アクティブで開いて、呼び出しもとのウィンドウにフォーカスを残したままにするには Form の ShowWithoutActivation プロパティを override して true を返すようにすれば良い。
    protected override bool ShowWithoutActivation
{
get
{
return true;
}
}
posted by なまい at 12:54| Comment(0) | C# | このブログの読者になる | 更新情報をチェックする

2010年10月30日

ウィンドウを表示させないようにする(タスクバー、Alt+Tabにも)

ウィンドウを全く表示させないようにする。
ShowInTaskBarプロパティをfalseにしてもAlt+Tabには表示されてしまうがフォームのCreateParamsプロパティをoverrideし、ウィンドウが表示されなくする。
    protected override CreateParams CreateParams
{
get {
const int WS_EX_TOOLWINDOW = 0x80;
const long WS_POPUP = 0x80000000L;
const int WS_VISIBLE = 0x10000000;
const int WS_SYSMENU = 0x80000;
const int WS_MAXIMIZEBOX = 0x10000;

CreateParams cp = base.CreateParams;
cp.ExStyle = WS_EX_TOOLWINDOW;
cp.Style = unchecked((int) WS_POPUP) | WS_VISIBLE | WS_SYSMENU | WS_MAXIMIZEBOX;
cp.Width = 0;
cp.Height = 0;

return cp;
}
}
posted by なまい at 19:07| Comment(0) | C# | このブログの読者になる | 更新情報をチェックする

2010年02月25日

WindowsXPでClearTypeフォントを美しく表示する

最近、WindowsXPをクリーンインストールしたのだが、ClearTypeフォントが美しく表示されない。
画面のプロパティからスクリーンフォントの縁を滑らかにしてもダメ。
XP用のメイリオをインストールしても、うすくぼやけてとても使えたもんじゃない。

以前WindowsXP SP2で設定したときはきれいに表示されていたので、SP3をクリーンインストールしたから?とかいろいろ考えていたのだが、偶然MicrosoftからClearTypeフォントの設定ツールがでているのを発見。

その名も「ClearType Tuner」
Windows 7のコントロールパネルに入っているやつ。

早速インストールして使ってみた。インストールするとコントロールパネルに「ClearType Tuning」という項目が追加されるので、こいつを起動してあとはウィザードに従って設定していくだけ。
無事、WindowsXPでもきれいにClearTypeフォントが表示されるようになって満足。

ダウンロード:
Microsoft Typography - ClearType Tuner PowerToy
posted by なまい at 13:02| Comment(0) | その他 | このブログの読者になる | 更新情報をチェックする

2010年02月20日

時間のかかる処理を別スレッドで処理する

時間のかかる処理を別スレッドで処理するには、System.Threading.Threadクラスを使用する。
別スレッド内からラベルなどのコントロールを操作するにはInvoke()メソッドを使用しないと例外が発生するので注意。
    // スレッドクラス
private System.Threading.Thread thread_ = null;

public Form1()
{
InitializeComponent();
this.button1.Click += new EventHandler(button1_Click);
}


private void button1_Click(object sender, EventArgs e)
{
//スレッドを作成&開始
thread_ = new System.Threading.Thread(new System.Threading.ThreadStart(Execute));
thread_.IsBackground = true;
this.thread_.SetApartmentState(System.Threading.ApartmentState.STA);
thread_.Start();
}


private void Execute()
{
// 時間のかかる処理をここで行う

// ラベルに進捗状況などを表示
this.Invoke(new MethodInvoker(Label1Update));
}


private void Label1Update()
{
this.label1.Text = "時間のかかる処理中";
}
posted by なまい at 22:24| Comment(0) | C# | このブログの読者になる | 更新情報をチェックする

2010年02月01日

64bit環境でAccessに接続する際の注意点

64bit環境でOleDbConnectionを使用してAccessに接続する際の注意点。
Accessは2003も2007も64bit環境はサポートしていないっぽいのでそのままでは接続できない。

プロジェクトのプロパティのビルドタブを開いて、プラットフォームターゲットで「x86」を選択すれば接続可能になる。

プロジェクト−プロパティ
posted by なまい at 13:13| Comment(0) | DB | このブログの読者になる | 更新情報をチェックする
×

この広告は1年以上新しい記事の投稿がないブログに表示されております。