2009/06/28

win7 比 vista 便宜 ... 20% off!

微軟在其網站上,正式公告售價:

昇級版售價:
* Windows 7 Home Premium (Upgrade): $119.99
* Windows 7 Professional (Upgrade): $199.99
* Windows 7 Ultimate (Upgrade): $219.99

完整版售價:

* Windows 7 Home Premium (Full): $199.99
* Windows 7 Professional (Full): $299.99
* Windows 7 Ultimate (Full): $319.99

這意味著,因應經濟不景氣,微軟大發慈悲心,大降價,以 Win7 Home Premium 為例大約降價 20%!

2009/06/23

xp, vista, win7 共舞 multi-boot -2

先前寫過一篇xp, vista, win7 共舞,後來又因為不知名的原因把某一個開機選項弄不見了。真的,不是故意為之。那問題來了,怎樣把之前的開機選項搞出來?

其實這問題或許最好的答案是養成備份習慣。不過因為是實驗機,所以我也就懶得備份,再說,工作機也不需要搞這東東。

BCDE FAQ....這文章還真怪,BCDEF...Ok Ok, 不離題,在這篇文章中提到要怎樣自己弄一個新的開機選項,請見 How to create a new Windows Vista operating system entry 這一條的說明。步驟大約如下:

1. bcdedit /copy {GuidToCopy} /d 「NewEntryDescription」
==> 我是這麼下命令的:
bcdedit /copy {current} /d "win7 enterprise"
==> 這樣一來,會把目前的開機選項複製並附在選單的最後。若是注意的話,會發現 Identifier 是新的,其餘的都是與 {current} 相同。

2. 用下列兩個命令來設定到你要的磁區,也就是「磁碟機」:
bcdedit /set {NewGuid} device partition=x:
bcdedit /set {NewGuid} osdevice partition=x:
==> 這邊的 {NewGuid} 就是上一條產生的 Identifier, 而 x: 就是你要的磁碟機

3. 用下列命令調整開機順序,不執行此命令也行
bcdedit /displayorder {NewGuid} /addlast

2009/06/12

screen capture

我們有一個應用程式,需要抓取全螢幕的畫面,有人會截取 PrtScn Keyboard 事件來達到目的,我當然認定這個方法非常不好,就像前面講的 mouse hook 一樣,別人一樣也可以做 keyboard hook。

後來用了某種 screen capture 的方法,結果把螢幕上所有東西都抓下來,或許這結果是某些人想要的,但是我們卻不要像滑鼠或是一些 Gesture 提示的畫面。目前找到一篇Screen Captures, Window Captures and Window Icon Captures with Spy++ style Window Finder!有不錯的範例,請自行前往觀看。

Touch 與 mouse 共舞

最近在搞 Windows 7 的 Multi Touch 應用程式,其中有幾項議題困擾很久,其中一項是 sleep(1) 已於前面說明。另一項是 Touch 發生時我們不想要有 Mouse Event, 我說的是不想要,不是不處理即可,這問題讓我煩到快抓狂。

不抱怨了,直接說答案,就是用 Global Mouse Hook, 然後把 Mouse Message 濾掉。是有不少例子在說明 mouse hook, 例如我看的最懂的是Processing Global Mouse and Keyboard Hooks in C#,卻沒有人講明白怎樣濾掉 mouse message.

事實上在該文中有答案,只是它沒明說而已。我直接寫一個範例片段來說明,當然說明直接放程式片段中:

// 註冊 global mouse hook
void TFormPaint::RegMouseHook()
{
MouseHookDelegate = gcnew HookProcDelegate(this, &TFormPaint::MouseHookProc);
MouseHookHandle = ::SetWindowsHookEx(WH_MOUSE_LL, MouseHookDelegate,
Marshal::GetHINSTANCE(System::Reflection::Assembly::GetExecutingAssembly()->GetModules()[0]),0);
}

// 我們處理的 mouse hook 的函式
int TFormPaint::MouseHookProc(int nCode, int wParam, IntPtr lParam)
{
WCHAR Buffer[30];

// 把 Mouse Hook 的訊息從 lParam 指標中取出來
MOUSEHOOKSTRUCT* mouseHookStruct=(MOUSEHOOKSTRUCT*)lParam.ToPointer();

// 只濾掉發生在本視窗的滑鼠事件,
// 所以要比對滑鼠所發生時的視窗
HWND CurHwnd = WindowFromPoint(mouseHookStruct->pt);
GetWindowText(CurHwnd, Buffer, 30);
String^ WindowTitle = gcnew String(Buffer);

// ☆重點來了,
// 當發現滑鼠事件是作用在我們的視窗上,就以
// return -1 來濾掉
if (WindowTitle->IndexOf(this->Text) != -1)
{
return -1;
}

// 下面這行非常重要,否則整個系統的滑鼠會因此壞掉
return CallNextHookEx(MouseHookHandle, nCode, wParam, lParam);
}

sleep 1 ms ?

還記得四月初時我寫的這一篇timer 與 while(1)嗎?最近在用 visual studio 開發應用程式時有用到 sleep() 函式來暫時停止程式運行,用我們的話說,就是我們要讓程式的執行頻率是 125 次/秒,也就是我們想要用 sleep(8) 來達到目的。sleep(8) 應該要能暫停 8ms, 結果實驗數據是 16ms, 甚至當我們調整成 sleep(1), 答案也一樣。

慘了,效率只有一半!這問題困擾很久,試著用 timer,答案一樣的令人沮喪,也試過透過 Windows Message 的方式,沒用。

好了,最後結果是參考timeBeginPeriod搭配 timeEndPeriod。因為這會改到系統的時間設定,因此記得要成對。

簡單寫個範例如下:
timeBeginPeriod(8);
sleep(8);
timeEndPeriod(8);


想對 Timer 有更進一步了解的人,可以自行參考Timer 介紹一文。

2009/06/08

xp, vista, win7 共舞 multi-boot

最近真的是離不開 M$ OS, 甚至一台電腦要裝九個作業系統,當然啦,是資源不足才需要這樣。問題來了,開機選單在 winxp 還可以透過界面修改,可是 vista, win7 全都不開放!現在研究後的心得如下,請在 vista or win7 下執行:

一、首先在 Command Prompt, 也就是 DOS command, 上用右鍵選「Run as Administrator」,這樣才有足夠的權限,若找不到的話請參考:
Start Menu->All Programs->Accessories->Command prompt(在上面點右鍵選擇"Run as administrator")

二、可以用 bcdedit /enum 列出所有開機選單,例如下面的是我的電腦的範例, # 號後面的是我加的註解:


Windows Boot Manager
--------------------
identifier {bootmgr}
device partition=D:
description Windows Boot Manager
locale en-US
inherit {globalsettings}
default {current}
resumeobject {42231781-52f5-11de-92a1-f650bd7a3f2b}
displayorder {ntldr}
{current}
{42231782-52f5-11de-92a1-f650bd7a3f2b}
{4223177e-52f5-11de-92a1-f650bd7a3f2b}
{b1252275-52ef-11de-ac3a-e7ceed221dbd}
toolsdisplayorder {memdiag}
timeout 30

Windows Legacy OS Loader
------------------------
identifier {ntldr}
device partition=D:
path \ntldr
description 舊版 Windows

# 可以用下列命令改掉
# bcdedit /set {ntldr} Description "XP 32/64"

Windows Boot Loader
-------------------
identifier {current}
device partition=C:
path \Windows\system32\winload.exe
description Microsoft Windows Vista
locale en-US
inherit {bootloadersettings}
osdevice partition=C:
systemroot \Windows
resumeobject {adc6e5dc-5450-11de-b61c-8253c0de8538}
nx OptIn
# 可以用下列命令將原來的"Microsoft Windows Vista" 改掉
# bcdedit /set {current} Description "Vista 32 en Enterprise"

Windows Boot Loader
-------------------
identifier {42231782-52f5-11de-92a1-f650bd7a3f2b}
device partition=I:
path \Windows\system32\winload.exe
description Windows 7
locale zh-TW
inherit {bootloadersettings}
recoverysequence {42231783-52f5-11de-92a1-f650bd7a3f2b}
recoveryenabled Yes
osdevice partition=I:
systemroot \Windows
resumeobject {42231781-52f5-11de-92a1-f650bd7a3f2b}
nx OptIn
# 可以用下列命令將原來的 "Windows 7" 改掉
# bcdedit /set {42231782-52f5-11de-92a1-f650bd7a3f2b} Description "Win7 64 Ultimate"

Windows Boot Loader
-------------------
identifier {4223177e-52f5-11de-92a1-f650bd7a3f2b}
device partition=H:
path \Windows\system32\winload.exe
description Windows 7
locale en-US
inherit {bootloadersettings}
recoverysequence {4223177f-52f5-11de-92a1-f650bd7a3f2b}
recoveryenabled Yes
osdevice partition=H:
systemroot \Windows
resumeobject {4223177d-52f5-11de-92a1-f650bd7a3f2b}
nx OptIn
# 可以用下列命令將原來的 "Windows 7" 改掉
# bcdedit /set {4223177e-52f5-11de-92a1-f650bd7a3f2b} Description "Win7 32 Ultimate"

Windows Boot Loader
-------------------
identifier {b1252275-52ef-11de-ac3a-e7ceed221dbd}
device partition=E:
path \Windows\system32\winload.exe
description Microsoft Windows Vista
locale en-US
inherit {bootloadersettings}
osdevice partition=E:
systemroot \Windows
resumeobject {b1252276-52ef-11de-ac3a-e7ceed221dbd}
nx OptIn
# 可以用下列命令將原來的 "Microsoft Windows Vista" 改掉
# bcdedit /set {b1252275-52ef-11de-ac3a-e7ceed221dbd} Description "Vista 64 Enterprise"


三、在上文提到的 {current} 還有 {default} 等選擇文字,其實就在 /enum 列出的 "identifier" 欄位裡面

四、 用 bcdedit /? 取得進一步資訊