2009年8月29日 星期六

Windows程式使用argc,argv參數

Console程式的進入點main函數的其中一個原型如下:
int main(int argc, char *argv[]);

透過argc與argv二個參數,可以用來取得程式執行時執行檔案的名稱及其執行參數。例如你下了指令:C:\>dir /b /l,argc參數會等於3表示包含檔名本身再加上二個參數,可以由argv參數取出分別為"dir", "/b"及"/l"這三個字串。

+ + +

Windows程式進入點WinMain原型為:
int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE, LPTSTR lpstrCmdLine, int nCmdShow);

假如想要像Console程式一樣能夠取得argc及argv參數,底下提供二個方法。

1,
直接使用__argc及__argv這二個全域變數即可。(如果你的程式是Unicode程式,則使用__wargv)

2,
使用Win32 API GetCommandLineWCommandLineToArgvW。(這個方法僅支援Unicode格式,同時第一個取出的參數不是執行檔名)

2009年8月19日 星期三

PNG秀圖的處理

首先看看底下這張PNG格式圖檔,正確顯示結果應該如下原圖所示。


載入後以API AlphaBlend作Per-Pixel Alpha Blend如下所示,結果是不正確。


檢查AlphaBlend規格發現,以AlphaBlend作Per-Pixel Alpha Blend時,會以底下公式計算每一個像素的值。

Dst.Red = Src.Red + (1 - Src.Alpha) * Dst.Red;
Dst.Green = Src.Green + (1 - Src.Alpha) * Dst.Green;
Dst.Blue = Src.Blue + (1 - Src.Alpha) * Dst.Blue;

要作正確PNG秀圖(或者說有帶Alpha Channel的圖),底下列出虛擬碼。

if (255 == Src.Alpha)
{
Dst.Red = Src.Red;
Dst.Green = Src.Green;
Dst.Blue = Src.Blue;
}
else if (0 != Src.Alpha)
{
Dst.Red = Src.Red * Src.Alpha + (1 - Src.Alpha) * Dst.Red;
Dst.Green = Src.Green * Src.Alpha + (1 - Src.Alpha) * Dst.Green;
Dst.Blue = Src.Blue * Src.Alpha + (1 - Src.Alpha) * Dst.Blue;
}

;

AlphaBlend測試代碼:
BLENDFUNCTION bf;
bf.BlendOp = AC_SRC_OVER; // 目前僅支援此操作.
bf.BlendFlags = 0; // 必須為0
bf.SourceConstantAlpha = 255; // 使用Per-Pixel Alpha
bf.AlphaFormat = AC_SRC_ALPHA; // 使用Per-Pixel Alpha

dc.AlphaBlend(0, 0, sz.cx, sz.cy, memdc, 0, 0, sz.cx, sz.cy, bf);

2009年8月16日 星期日

實作組合語言除錯器

這幾天寫了個簡易版的組合語言除錯器。原因是當我在整理並重新組譯之前寫的一個組合語言小程式時,找到了一個小Bug。Debug的過程花了點時間,因為手上還沒有Debugger可用。所以就動手把之前就已計劃有需要製作的除錯器實作了一個可用的簡單版本出來,目前俱備基本的Memmory Dump, Unassemble, Breakpoints 等除錯功能。

這張圖裡面可以看到的指令好像跟x86指令集裡的有點不大一樣,暫存器看起來更不同。沒錯,因為這是我設計的虛擬機器指令集,我把它命名為 jaja XD

2009年8月13日 星期四

實驗中國象棋 for Windows Mobile Port

花了一點時間把以前作的實驗象棋植移上去,純粹當作睡前消磨時間的小玩意。這次還新增了簡單的開局資料,至少能避免每次都走出一模一樣的棋局。


PS:WM PC 模擬器在有Focus的情況下PrintScr鍵似乎無效。

2009年8月11日 星期二

聰明過頭的編譯器

作個小實驗來看看我們所使用的編譯器有多聰明,看了實驗結果後也該小心在意,別因為編譯器太過聰明,聰明反被聰明誤,壞了事。

工具:MS VS.NET C++ 2003
平台:MS Windows XP SP2
void Foo()
{
int a = 0;
if (10 == a)
a = 1;
}

void Bar()
{
int a = 0;
if (10 == a)
a = 1;
}

int main()
{
cout << "&Foo = " << &Foo << "\n";
cout << "&Bar = " << &Bar << "\n";
}
以上很簡單的一小段程式碼。

Debug版本的執行結果如下。

&Foo = 0041B5A0
&Bar = 0041BFA0

而Release版本的執行結果如下。

&Foo = 00401130
&Bar = 00401130

顯然Release版時,Foo及Bar這二個函式被當作同一個函式,因為二者實作內容完全相同(或最佳化後相同),只有名稱不同。雖然這個情況很少見,但看到這樣的結果,還是要小心謹慎,以免不小心寫出莫名其妙不知問題在那裡的程式來。

;

同樣的程式在VS.NET 2005及2008上測試結果也是會發生同樣的問題。
Related Posts Plugin for WordPress, Blogger...