2009/04/27

關於視窗的一點心得


/// how to capture window @ mouse?
// capture the window under the cursor's position
IntPtr hWnd = Win32.WindowFromPoint(Cursor.Position);
// handle
_textBoxHandle.Text = string.Format("{0}", hWnd.ToInt32().ToString());

// class
_textBoxClass.Text = this.GetClassName(hWnd);

// caption
_textBoxText.Text = this.GetWindowText(hWnd);

Win32.Rect rc = new Win32.Rect();
Win32.GetWindowRect(hWnd, ref rc);

// rect
_textBoxRect.Text = string.Format("[{0} x {1}], ({2},{3})-({4},{5})", rc.right - rc.left, rc.bottom - rc.top, rc.left, rc.top, rc.right, rc.bottom);

/// 自己的 Root Form Handler
if (hWnd == IntPtr.Zero)
{
}

/// 如何抓 window image?

// capture that window
Image image = ScreenCapturing.GetWindowCaptureAsBitmap(handle);

// fire our image read event, which the main window will display for us
this.OnImageReadyForDisplay(image);

/// 如何等候 Image 已經畫好再做事?

public event DisplayImageEventHandler ImageReadyForDisplay;
ImageReadyForDisplay += new DisplayImageEventHandler(this.DisplayImage);
if (ImageReadyForDisplay != null)
ImageReadyForDisplay(image, false, PictureBoxSizeMode.CenterImage);

/// 如何抓例外
try
{
if (this.ImageReadyForDisplay != null)
this.ImageReadyForDisplay(image, false, PictureBoxSizeMode.CenterImage);
}
catch(Exception ex)
{
Debug.WriteLine(ex);
}

public class WindowHighlighter
{
public static void Highlight(IntPtr hWnd)
{
const float penWidth = 3;
Win32.Rect rc = new Win32.Rect();
Win32.GetWindowRect(hWnd, ref rc);

IntPtr hDC = Win32.GetWindowDC(hWnd);
if (hDC != IntPtr.Zero)
{
using (Pen pen = new Pen(Color.Black, penWidth))
{
using (Graphics g = Graphics.FromHdc(hDC))
{
g.DrawRectangle(pen, 0, 0, rc.right - rc.left - (int)penWidth, rc.bottom - rc.top - (int)penWidth);
}
}
}
Win32.ReleaseDC(hWnd, hDC);
}

public static void Refresh(IntPtr hWnd)
{
Win32.InvalidateRect(hWnd, IntPtr.Zero, 1);
Win32.UpdateWindow(hWnd);
Win32.RedrawWindow(hWnd, IntPtr.Zero, IntPtr.Zero, Win32.RDW_FRAME | Win32.RDW_INVALIDATE | Win32.RDW_UPDATENOW | Win32.RDW_ALLCHILDREN);
}
}

2009/04/23

timer 與 while(1)

連續貼三篇文章,有的寫的很簡單卻搞到很頭痛,還有一個最頭痛的沒貼上來,等整理心得出來後再來與大家分享。這邊講一個被 M$ 氣的半死的一項。

想當然爾,timer() 的單位的 ms, 所以若設定 1ms 與 10ms, 被呼叫的頻率差應該是 10 倍吧?答案是....No!!! 究竟是多少?網路上有人在問要怎樣設定 timer 到微秒的等級,嗚呼哀哉。目前我們測試的 timer 最快也就 60HZ 而已。

因為 timer() 無法達到預期目標,那麼就用 while(1), 又怕吃掉系統資源,以前知道要用 usleep(), 不要說這會讓系統負擔變重,事實上是我們找不到!,後來大膽測試 while(1), 結果卻發現頻率夠高,而且而且,系統負擔竟然出奇的輕!偉哉,M$!

這邊要提醒的是,我說 while(1) 不會造成系統負擔過重的原因不是 OS 排程做的好,而是 while() 裡面做的是 device IO。至於如何調整 sleep() 的時間單位?答案有機會再揭曉

Visual Studio 中的記憶體管理

這篇也是同事的心得,因為程式一開始沒有作記憶體釋放動作,因而造成整個系統資源被吃光,希望不要再有人犯同樣錯誤。畢竟保持環境清潔人人有責。

C++中有new 和 gcnew(garbage collection new)(C#裡面的new 其實就是gcnew)

原則上managed的物件都只能用gcnew去創造

而unmanaged則是用new

這兩個東西的差別是需不需要主動去做garbage collection(delete的動作)

在managed的程式中

隔一段時間,GC會去判斷目前的記憶體空間是否沒有reference

沒有的話就會釋放出來

也可以採用GC::Collect()去做這件事(不需要特別再對每個ref做delete,delete沒有實際效果)

new的話就需要自己在確定沒有使用的時候去把他delete掉

另外還有一類,使用global的函式所給出的handle(比如canvas裡用的CreatePen)

不知道為什麼,他不會計算到程式的記憶體使用量裡面(一直create不會發現程式記憶體用輛增加)

但是因為沒有清掉,所以還是會在使用過多的時候發生問題(程式crash)

所以得要去做DeleteObject的動作

怎樣讓程式不會重複被執行

最近我只在 M$ 平台上混,真的被氣死了。話不多說,來說一個怎樣讓程式不會重複被叫起來的方法,這是同仁的心得,我代貼而已。

主要使用到CreateMutex()函數和GetLastError()以及一個常量
ERROR_ALREADY_EXISTS.

下面為sample code:

HANDLE hMutex = CreateMutex(NULL, false, "Process");
if (GetLastError() == ERROR_ALREADY_EXISTS)
{
CloseHandle(hMutex);
MessageBox(Application->Handle, "程序已經執行中,不能重覆啟動!", "提示",
MB_OK);

return 0;
}

參考網頁 : http://hi.baidu.com/machh03/blog/item/52c0cc3864fd5b2697ddd815.html