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 GetCommandLineW及CommandLineToArgvW。(這個方法僅支援Unicode格式,同時第一個取出的參數不是執行檔名)
2009年8月29日 星期六
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測試代碼:

載入後以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日 星期日
實作組合語言除錯器
2009年8月13日 星期四
實驗中國象棋 for Windows Mobile Port
2009年8月11日 星期二
聰明過頭的編譯器
作個小實驗來看看我們所使用的編譯器有多聰明,看了實驗結果後也該小心在意,別因為編譯器太過聰明,聰明反被聰明誤,壞了事。
工具:MS VS.NET C++ 2003
平台:MS Windows XP SP2
Debug版本的執行結果如下。
&Foo = 0041B5A0
&Bar = 0041BFA0
而Release版本的執行結果如下。
&Foo = 00401130
&Bar = 00401130
顯然Release版時,Foo及Bar這二個函式被當作同一個函式,因為二者實作內容完全相同(或最佳化後相同),只有名稱不同。雖然這個情況很少見,但看到這樣的結果,還是要小心謹慎,以免不小心寫出莫名其妙不知問題在那裡的程式來。
;
同樣的程式在VS.NET 2005及2008上測試結果也是會發生同樣的問題。
工具: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上測試結果也是會發生同樣的問題。
訂閱:
文章 (Atom)