2009/05/20

Programming with Windows 7 Multitouch & Gesture 續

軟體與硬體需求

當然要有硬體與作業系統及 SDK:
A multi-touch monitor
A PC or NB installed Windows 7
Installed Windows 7 SDK
Visual Studio(我用的是 Visual Studio 2008)

環境設定

設定Win7 SDK的路徑, 包含include與library都要設定:
Header :Declared in Winuser.h; include Windows.h.
Library:Include User32.lib

接下來請參考前一篇的資料結構,因為微軟的開發模式都差不多,在寫 Multitouch 與寫 Mouse 的方式很像,就是收 Message, 定義自己得 event handler, 底下就列出相關的 Message:


WM_GESTURE Message

Passes information about a gesture.

Parameters

wParam


Provides information identifying the gesture command and gesture-specific argument values. This information is retrieved by calling GetGestureInfo.

lParam

Provides information identifying the gesture command and gesture-specific argument values. This information is retrieved by calling GetGestureInfo.

Return Value

If an application processes this message, it should return 0.

If the application does not process the message, it must call DefWindowProc. Not doing so will cause the application to leak memory because the touch input handle will not be closed and associated process memory will not be freed.

WM_GESTURENOTIFY Message

Indicates that a gesture message is about to be received.

Parameters

wParam


Unused.

lParam

A pointer to a GESTURENOTIFYSTRUCT.

Return Value

If an application processes this message, it should return 0.

Remarks

When the WM_GESTURENOTIFY message is received, the application can use SetGestureConfig to specify the gestures to receive.

Examples

switch (message)
{
case WM_GESTURENOTIFY:
{
GESTURECONFIG gc = {0,GC_ALLGESTURES,0};
BOOL bResult = SetGestureConfig(hWnd,0,1,&gc,sizeof(GESTURECONFIG));

if(!bResult)
{
// an error
}
}

break

GESTUREINFO Structure

Stores information about a gesture.
Syntax

typedef struct _GESTUREINFO {
UINT cbSize;
DWORD dwFlags;
DWORD dwID;
HWND hwndTarget;
POINTS ptsLocation;
DWORD dwInstanceID;
DWORD dwSequenceID;
ULONGLONG ullArguments;
UINT cbExtraArgs;

} GESTUREINFO, *PGESTUREINFO;

Members

cbSize

The size of the structure, in bytes. The caller must set this to sizeof(GESTUREINFO).

dwFlags

The state of the gesture. For additional information, see Remarks.

dwID

The identifier of the gesture command.

hwndTarget

A handle to the window that is targeted by this gesture.

ptsLocation

A POINTS structure containing the coordinates associated with the gesture. These coordinates are always relative to the origin of the screen.

dwInstanceID

An internally used identifier for the structure.

dwSequenceID

An internally used identifier for the sequence.

ullArguments

An unsigned long long that contains the arguments for gestures that fit into 8 bytes.

cbExtraArgs

The size, in bytes, of extra arguments that accompany this gesture.

Remarks

The GESTUREINFO structure is retrieved by passing the handle to the gesture information structure to the GetGestureInfo function.

The following flags indicate the various states of the gestures and are stored in dwFlags.
Name Value Description
GF_BEGIN 0x00000001 Indicates a gesture is starting
GF_INERTIA 0x00000002 Indicates a gesture has triggered inertia
GF_END 0x00000004 Indicates a gesture has finished

Note Most applications should ignore the GID_BEGIN and GID_END messages and pass them to DefWindowProc. These messages are used by the default gesture handler and application behaviour is undefined when the GID_BEGIN and GID_END messages are consumed by a third party application.

The following table indicates the various identifiers for gestures.


Name Value Description
GID_BEGIN 1 Indicates a gesture is starting.
GID_END 2 Indicates a gesture is ending.
GID_ZOOM 3 Indicates the zoom gesture.
GID_PAN 4 Indicates the pan gesture.
GID_ROTATE 5 Indicates the rotation gesture.
GID_TWOFINGERTAP 6 Indicates the two-finger tap gesture.
GID_ROLLOVER 7 Indicates the rollover gesture.
Examples

GESTUREINFO gestureInfo = {0};

gestureInfo.cbSize = sizeof(gestureInfo);

BOOL bResult = GetGestureInfo((HGESTUREINFO)lParam, &gestureInfo);


dwCommand dwArguments ptsLocation
Pan Distance between contacts Current center of gesture
Zoom Distance between contacts Current center of gesture
Rotate Absolute angle on rotate start, delta on updates Current center of gesture
Two-finger tap NA Current center of gesture

GESTURENOTIFYSTRUCT Structure

When transmitted with WM_GESTURENOTIFY messages, passes information about a gesture.

Syntax

typedef struct tagGESTURENOTIFYSTRUCT {
UINT cbSize;
DWORD dwFlags;
HWND hwndTarget;
POINTS ptsLocation;
DWORD dwInstanceID;

} GESTURENOTIFYSTRUCT, *PGESTURENOTIFYSTRUCT;

Members

cbSize

The size of the structure.

dwFlags

Reserved for future use.

hwndTarget

The target window for the gesture notification.

ptsLocation

The location of the gesture.

dwInstanceID

A specific gesture instance with gesture messages starting with GID_START and ending with GID_END.

GESTURECONFIG Structure

Gets and sets the configuration for enabling gesture messages and the type of this configuration.

Syntax

typedef struct _GESTURECONFIG {
DWORD dwID;
DWORD dwWant;
DWORD dwBlock;

} GESTURECONFIG, *PGESTURECONFIG;

Members

dwID

The identifier for the type of configuration that will have messages enabled or disabled. For more information, see Remarks.

dwWant

The messages to enable.

dwBlock

The messages to disable.

Remarks

When you pass this structure, the dwID member contains information for a set of gestures. This determines what the other flags will mean. If you set flags for pan messages, they will be different from those flags that are set for rotation messages.

The following table indicates the various identifiers for gestures that are supported by the dwID member of the GESTURECONFIG structure. Note that setting dwID to 0 indicates that global gesture configuration flags are set.

GetGestureInfo Function

Retrieves a gesture information structure given a handle to the gesture information.

Syntax

BOOL WINAPI GetGestureInfo(

__in HGESTUREINFO hGestureInfo,

__out PGESTUREINFO pGestureInfo

);

Parameters

hGestureInfo [in]

The gesture information handle.

pGestureInfo [out]

A pointer to the gesture information structure.

Return Value

If the function succeeds, the return value is nonzero.

If the function fails, the return value is zero. To get extended error information, use the GetLastError function.

Examples

GESTUREINFO gestureInfo = {0};

gestureInfo.cbSize = sizeof(gestureInfo);

BOOL bResult = GetGestureInfo((HGESTUREINFO)lParam, &gestureInfo);

SetGestureConfig Function

Configures the messages that are sent from a window for multitouch gestures.

Syntax

BOOL WINAPI SetGestureConfig(
__in HWND hwnd,
__in DWORD dwReserved,
__in UINT cIDs,
__in PGESTURECONFIG pGestureConfig,
__in UINT cbSize
);

Parameters

hwnd [in]

A handle to the window to set the gesture configuration on.

dwReserved [in]

This value is reserved and must be set to 0.

cIDs [in]

A count of the gesture configuration structures that are being passed.

pGestureConfig [in]

An array of gesture configuration structures that specify the gesture configuration.

cbSize [in]

The size of the array of gesture configuration structures.

Return Value

If the function succeeds, the return value is nonzero.

If the function fails, the return value is zero. To get extended error information, use the GetLastError function.

Programming with Windows 7 Multitouch & Gesture

請參考Microsoft MSDN Windows Touch for Developer一文,以及微軟「阿倫」的部落格的說明。

我這邊先直接貼一些資料結構的定義:


#if(WINVER >= 0x0601)

/*
* Gesture defines and functions
*/

/*
* Gesture information handle
*/
DECLARE_HANDLE(HGESTUREINFO);


/*
* Gesture flags - GESTUREINFO.dwFlags
*/
#define GF_BEGIN 0x00000001
#define GF_INERTIA 0x00000002
#define GF_END 0x00000004

/*
* Gesture IDs
*/
#define GID_BEGIN 1
#define GID_END 2
#define GID_ZOOM 3
#define GID_PAN 4
#define GID_ROTATE 5
#define GID_TWOFINGERTAP 6
#define GID_PRESSANDTAP 7
#define GID_ROLLOVER GID_PRESSANDTAP

/*
* Gesture information structure
* - Pass the HGESTUREINFO received in the WM_GESTURE message lParam into the
* GetGestureInfo function to retrieve this information.
* - If cbExtraArgs is non-zero, pass the HGESTUREINFO received in the WM_GESTURE
* message lParam into the GetGestureExtraArgs function to retrieve extended
* argument information.
*/
typedef struct tagGESTUREINFO {
UINT cbSize; // size, in bytes, of this structure (including variable length Args field)
DWORD dwFlags; // see GF_* flags
DWORD dwID; // gesture ID, see GID_* defines
HWND hwndTarget; // handle to window targeted by this gesture
POINTS ptsLocation; // current location of this gesture
DWORD dwInstanceID; // internally used
DWORD dwSequenceID; // internally used
ULONGLONG ullArguments; // arguments for gestures whose arguments fit in 8 BYTES
UINT cbExtraArgs; // size, in bytes, of extra arguments, if any, that accompany this gesture
} GESTUREINFO, *PGESTUREINFO;
typedef GESTUREINFO const * PCGESTUREINFO;


/*
* Gesture notification structure
* - The WM_GESTURENOTIFY message lParam contains a pointer to this structure.
* - The WM_GESTURENOTIFY message notifies a window that gesture recognition is
* in progress and a gesture will be generated if one is recognized under the
* current gesture settings.
*/
typedef struct tagGESTURENOTIFYSTRUCT {
UINT cbSize; // size, in bytes, of this structure
DWORD dwFlags; // unused
HWND hwndTarget; // handle to window targeted by the gesture
POINTS ptsLocation; // starting location
DWORD dwInstanceID; // internally used
} GESTURENOTIFYSTRUCT, *PGESTURENOTIFYSTRUCT;

/*
* Gesture argument helpers
* - Angle should be a double in the range of -2pi to +2pi
* - Argument should be an unsigned 16-bit value
*/
#define GID_ROTATE_ANGLE_TO_ARGUMENT(_arg_) ((USHORT)((((_arg_) + 2.0 * 3.14159265) / (4.0 * 3.14159265)) * 65535.0))
#define GID_ROTATE_ANGLE_FROM_ARGUMENT(_arg_) ((((double)(_arg_) / 65535.0) * 4.0 * 3.14159265) - 2.0 * 3.14159265)

/*
* Gesture information retrieval
* - HGESTUREINFO is received by a window in the lParam of a WM_GESTURE message.
*/
WINUSERAPI
BOOL
WINAPI
GetGestureInfo(
__in HGESTUREINFO hGestureInfo,
__out PGESTUREINFO pGestureInfo);

/*
* Gesture extra arguments retrieval
* - HGESTUREINFO is received by a window in the lParam of a WM_GESTURE message.
* - Size, in bytes, of the extra argument data is available in the cbExtraArgs
* field of the GESTUREINFO structure retrieved using the GetGestureInfo function.
*/
WINUSERAPI
BOOL
WINAPI
GetGestureExtraArgs(
__in HGESTUREINFO hGestureInfo,
__in UINT cbExtraArgs,
__out_bcount(cbExtraArgs) PBYTE pExtraArgs);

/*
* Gesture information handle management
* - If an application processes the WM_GESTURE message, then once it is done
* with the associated HGESTUREINFO, the application is responsible for
* closing the handle using this function. Failure to do so may result in
* process memory leaks.
* - If the message is instead passed to DefWindowProc, or is forwarded using
* one of the PostMessage or SendMessage class of API functions, the handle
* is transfered with the message and need not be closed by the application.
*/
WINUSERAPI
BOOL
WINAPI
CloseGestureInfoHandle(
__in HGESTUREINFO hGestureInfo);


/*
* Gesture configuration structure
* - Used in SetGestureConfig and GetGestureConfig
* - Note that any setting not included in either GESTURECONFIG.dwWant or
* GESTURECONFIG.dwBlock will use the parent window's preferences or
* system defaults.
*/
typedef struct tagGESTURECONFIG {
DWORD dwID; // gesture ID
DWORD dwWant; // settings related to gesture ID that are to be turned on
DWORD dwBlock; // settings related to gesture ID that are to be turned off
} GESTURECONFIG, *PGESTURECONFIG;

/*
* Gesture configuration flags - GESTURECONFIG.dwWant or GESTURECONFIG.dwBlock
*/

/*
* Common gesture configuration flags - set GESTURECONFIG.dwID to zero
*/
#define GC_ALLGESTURES 0x00000001

/*
* Zoom gesture configuration flags - set GESTURECONFIG.dwID to GID_ZOOM
*/
#define GC_ZOOM 0x00000001

/*
* Pan gesture configuration flags - set GESTURECONFIG.dwID to GID_PAN
*/
#define GC_PAN 0x00000001
#define GC_PAN_WITH_SINGLE_FINGER_VERTICALLY 0x00000002
#define GC_PAN_WITH_SINGLE_FINGER_HORIZONTALLY 0x00000004
#define GC_PAN_WITH_GUTTER 0x00000008
#define GC_PAN_WITH_INERTIA 0x00000010

/*
* Rotate gesture configuration flags - set GESTURECONFIG.dwID to GID_ROTATE
*/
#define GC_ROTATE 0x00000001

/*
* Two finger tap gesture configuration flags - set GESTURECONFIG.dwID to GID_TWOFINGERTAP
*/
#define GC_TWOFINGERTAP 0x00000001

/*
* PressAndTap gesture configuration flags - set GESTURECONFIG.dwID to GID_PRESSANDTAP
*/
#define GC_PRESSANDTAP 0x00000001
#define GC_ROLLOVER GC_PRESSANDTAP

#define GESTURECONFIGMAXCOUNT 256 // Maximum number of gestures that can be included
// in a single call to SetGestureConfig / GetGestureConfig

WINUSERAPI
BOOL
WINAPI
SetGestureConfig(
__in HWND hwnd, // window for which configuration is specified
__in DWORD dwReserved, // reserved, must be 0
__in UINT cIDs, // count of GESTURECONFIG structures
__in_ecount(cIDs) PGESTURECONFIG pGestureConfig, // array of GESTURECONFIG structures, dwIDs will be processed in the
// order specified and repeated occurances will overwrite previous ones
__in UINT cbSize); // sizeof(GESTURECONFIG)


#define GCF_INCLUDE_ANCESTORS 0x00000001 // If specified, GetGestureConfig returns consolidated configuration
// for the specified window and it's parent window chain

WINUSERAPI
BOOL
WINAPI
GetGestureConfig(
__in HWND hwnd, // window for which configuration is required
__in DWORD dwReserved, // reserved, must be 0
__in DWORD dwFlags, // see GCF_* flags
__in PUINT pcIDs, // *pcIDs contains the size, in number of GESTURECONFIG structures,
// of the buffer pointed to by pGestureConfig
__inout_ecount(*pcIDs) PGESTURECONFIG pGestureConfig,
// pointer to buffer to receive the returned array of GESTURECONFIG structures
__in UINT cbSize); // sizeof(GESTURECONFIG)

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

2009/03/30

resource:///

繼上次談Fennec之後, 發現 Firefox 竟然支援 resource:/// 這種 url. 當時在玩 Fennec 的那十分鐘裡,找不到設定畫面,我就是透過 about:config 來做設定 proxy 的,而 resource:/// 可以快速開啟 Local File,尤其是安裝 Firefox 的目錄下。

不過....據說目前還有漏洞....

2009/03/27

嵌入式瀏覽器又多一椿 Fennec/Firefox

可以說,Fennec 是 Firefox 的兒子!
懶得貼太多東西,請見下列網址,感覺非常棒,雖然要稱之為嵌入式恐怕還太早,但是非常棒!有機會可以跟 Ubuntu 的 Netbook(Remix)比比看。

先讀讀 http://shiuan-pc.blogspot.com/2008/10/fennecmozilla.html
裡頭會講到 windows 上也可以跑,網址: http://ftp.mozilla.org/pub/mozilla.org/mobile/fennec-1.0a1.en-US.win32.zip
https://wiki.mozilla.org/Mobile/FennecVision
http://www.mozilla.org/projects/fennec/1.0a1/releasenotes/

2009/02/22

把二進位內容放進 shell script

貼過一篇 把文字檔放進 C 執行檔中。記得曾貼過類似下面的文章將二進位內容放進 shell 中,有興趣的人請看舊作建立自解壓檔一文,現在再來貼一次作法類似的文章。

分兩個檔,一個叫 addpayload.sh, 一個叫 install.sh.in, 前者如下:


#!/bin/bash

# Check for payload format option (default is uuencode).
uuencode=1
if [[ "$1" == '--binary' ]]; then
binary=1
uuencode=0
shift
fi
if [[ "$1" == '--uuencode' ]]; then
binary=0
uuencode=1
shift
fi

if [[ ! "$1" ]]; then
echo "Usage: $0 [--binary | --uuencode] PAYLOAD_FILE"
exit 1
fi


if [[ $binary -ne 0 ]]; then
# Append binary data.
sed \
-e 's/uuencode=./uuencode=0/' \
-e 's/binary=./binary=1/' \
install.sh.in >install.sh
echo "PAYLOAD:" >> install.sh

cat $1 >>install.sh
fi
if [[ $uuencode -ne 0 ]]; then
# Append uuencoded data.
sed \
-e 's/uuencode=./uuencode=1/' \
-e 's/binary=./binary=0/' \
install.sh.in >install.sh
echo "PAYLOAD:" >> install.sh

cat $1 | uuencode - >> install.sh
fi


install.sh.in 是個樣本檔,template file, 最後會產生 install.sh 才是加了二進位內容的 shell script....原文有執行例,請自行前往觀看怎麼執行。


#!/bin/bash

uuencode=1
binary=0

function untar_payload()
{
match=$(grep --text --line-number '^PAYLOAD:$' $0 | cut -d ':' -f 1)
payload_start=$((match + 1))
if [[ $binary -ne 0 ]]; then
tail -n +$payload_start $0 | tar -tzvf -
fi
if [[ $uuencode -ne 0 ]]; then
tail -n +$payload_start $0 | uudecode | tar -tzvf -
fi
}

read -p "Install files? " ans
if [[ "${ans:0:1}" || "${ans:0:1}" ]]; then
untar_payload
# Do remainder of install steps.
fi

exit 0

2009/02/09

QEMU 與 VirtualBox 的影像檔互換

QEMU img to VirtualBox vdi
代碼:
VBoxManage convertdd qemu.img qemu.vdi

或是
代碼:
./vditool DD qemu.vdi qemu.img


VirtualBox vdi to QEMU img
代碼:
./vditool COPYDD virtualbox.vdi virtualbox.img

initrd 機制

這篇文章是因為他寫的好,有在看我的文章的會比較容易找到。

cpio-initrd 的處理流程

1. boot loader 把內核以及 initrd 文件加載到內存的特定位置。

2. 內核判斷initrd的文件格式,如果是cpio格式。

3. 將initrd的內容釋放到rootfs中。

4. 執行initrd中的/init文件,執行到這一點,內核的工作全部結束,完全交給/init文件處理。

image-initrd的處理流程

1. boot loader把內核以及initrd文件加載到內存的特定位置。

2. 內核判斷initrd的文件格式,如果不是cpio格式,將其作為image-initrd處理。

3. 內核將initrd的內容保存在rootfs下的/initrd.image文件中。

4. 內核將/initrd.image的內容讀入/dev/ram0設備中,也就是讀入了一個內存盤中。

5. 接著內核以可讀寫的方式把/dev/ram0設備掛載為原始的根文件系統。

6. .如果/dev/ram0被指定為真正的根文件系統,那麼內核跳至最後一步正常啟動。

7. 執行initrd上的/linuxrc文件,linuxrc通常是一個腳本文件,負責加載內核訪問根文件系統必須的驅動, 以及加載根文件系統。

8. /linuxrc執行完畢,常規根文件系統被掛載

9. 如果常規根文件系統存在/initrd目錄,那麼/dev/ram0將從/移動到/initrd。否則如果/initrd目錄不存在, /dev/ram0將被卸載。

10. 在常規根文件系統上進行正常啟動過程 ,執行/sbin/init。

cpio-initrd的製作方法更加簡單

cpio-initrd的製作非常簡單,通過兩個命令就可以完成整個製作過程

#假設當前目錄位於準備好的initrd文件系統的根目錄下
bash# find . | cpio -c -o > ../initrd.img
bash# gzip ../initrd.img


傳統initrd的製作過程比較繁瑣,需要如下六個步驟

#假設當前目錄位於準備好的initrd文件系統的根目錄下
bash# dd if=/dev/zero of=../initrd.img bs=512k count=5
bash# mkfs.ext2 -F -m0 ../initrd.img
bash# mount -t ext2 -o loop ../initrd.img /mnt
bash# cp -r * /mnt
bash# umount /mnt
bash# gzip -9 ../initrd.img

2009/01/14

Multi-Touch & Gesture support on 最新的 VS 2008/.NET framework 3.5

==== Gesture ====

InkEdit.Gesture Event (Microsoft.Ink)
Basic C# Visual C++ J# JScript .NET Framework Class Library InkEdit..::.Gesture Event InkEdit Class Example See Also Send Feedback Updated: November 2007 Occurs when an application gesture is recognized. Namespace: Microsoft.Ink Assembly: Microsoft.Ink (in Microsoft.Ink.dll ...
Source: microsoft.ink

InkOverlay.Gesture Event (Microsoft.Ink)
Basic C# Visual C++ J# JScript .NET Framework Class Library InkOverlay..::.Gesture Event InkOverlay Class Example See Also Send Feedback Updated: November 2007 Occurs when an application gesture is recognized. Namespace: Microsoft.Ink Assembly: Microsoft.Ink (in Microsoft.Ink.dll ...
Source: microsoft.ink

InkCollector.Gesture Event (Microsoft.Ink)
Basic C# Visual C++ J# JScript .NET Framework Class Library InkCollector..::.Gesture Event InkCollector Class Example See Also Send Feedback Updated: November 2007 Occurs when an application gesture is recognized. Namespace: Microsoft.Ink Assembly: Microsoft.Ink (in Microsoft.Ink.dll ...
Source: microsoft.ink

InkPicture.Gesture Event (Microsoft.Ink)
Basic C# Visual C++ J# JScript .NET Framework Class Library InkPicture..::.Gesture Event InkPicture Class Example See Also Send Feedback Updated: November 2007 Occurs when an application gesture is recognized. Namespace: Microsoft.Ink Assembly: Microsoft.Ink (in Microsoft.Ink.dll ...
Source: microsoft.ink

Gesture Event Event (Windows)
InkEdit.Gesture Event Occurs when an application gesture is recognized. Syntax HRESULT Gesture( [in] IInkCursor *Cursor, [in] IInkStrokes *Strokes, [in] VARIANT Gestures, [in, out] VARIANT ...
Source: TabletandTouch

InputBinding.Gesture Property (System.Windows.Input)
Visual C++ J# JScript .NET Framework Class Library InputBinding..::.Gesture Property InputBinding Class Example See Also Send Feedback Updated: November ... com/winfx/xaml/presentationSyntaxVisual Basic (Declaration) Public Overridable Property Gesture As InputGestureVisual Basic (Usage) Dim instance As InputBinding Dim value ...
Source: System.Windows.Input

Gesture Class (Microsoft.Ink)
Basic C# Visual C++ J# JScript .NET Framework Class Library Gesture Class Members See Also Send Feedback Updated: November 2007 Represents the ability to query particular properties of a gesture returned from a gesture recognition. Namespace: Microsoft.Ink Assembly: Microsoft ...
Source: microsoft.ink

MouseBinding.Gesture Property (System.Windows.Input)
Basic C# Visual C++ J# JScript .NET Framework Class Library MouseBinding..::.Gesture Property MouseBinding Class Example See Also Send Feedback Updated: November 2007 Gets or sets the gesture associated with this MouseBinding. Namespace: System.Windows.Input Assembly: PresentationCore (in PresentationCore ...
Source: System.Windows.Input

Gesture Event Event (Windows)
InkCollector.Gesture Event Occurs when an application-specific gesture is recognized. Syntax void Gesture( [in] IInkCursor *Cursor, [in] IInkStrokes *Strokes, [in] VARIANT Gestures, [in, out ...
Source: TabletandTouch

Gesture Event Event (Windows)
InkOverlay.Gesture Event Occurs when an application-specific gesture is recognized. Syntax void Gesture( [in] IInkCursor *Cursor, [in] IInkStrokes *Strokes, [in] VARIANT Gestures, [in, out ...
Source: TabletandTouch

Gesture Event Event (Windows)
InkPicture.Gesture Event Occurs when an application-specific gesture is recognized. Syntax void Gesture( [in] IInkCursor *Cursor, [in] IInkStrokes *Strokes, [in] VARIANT Gestures, [in, out ...
Source: TabletandTouch

KeyBinding.Gesture Property (System.Windows.Input)
Basic C# Visual C++ J# JScript .NET Framework Class Library KeyBinding..::.Gesture Property KeyBinding Class Example See Also Send Feedback Updated: November 2007 Gets or sets the gesture associated with this KeyBinding. Namespace: System.Windows.Input Assembly: PresentationCore (in PresentationCore ...
Source: System.Windows.Input

InkCanvas.Gesture Event (System.Windows.Controls)
C# Visual C++ J# JScript .NET Framework Class Library InkCanvas..::.Gesture Event InkCanvas Class Example See Also Send Feedback Updated: November 2007 Occurs when the InkCanvas detects a gesture. Namespace: System.Windows.Controls Assembly: PresentationFramework (in PresentationFramework.dll) XMLNS for ...
Source: System.Windows.Controls

Gesture Members (Microsoft.Ink)
Members Include .NET Framework Members Include .NET Compact Framework Members Include XNA Framework Members .NET Framework Class Library Gesture Members Gesture Class Methods Properties See Also Send Feedback Updated: November 2007 Represents the ability to query particular properties of a ...
Source: microsoft.ink

Using the Microsoft Gesture Recognizer Only (Windows)
Using the Microsoft Gesture Recognizer Only You can use an ink collector (InkCollector, InkOverlay, or InkPicture) to access the default Microsoft gesture recognizer directly. To use an ink collector to access the gesture ...
Source: TabletandTouch

Gesture Properties (Microsoft.Ink)
Members Include .NET Framework Members Include .NET Compact Framework Members Include XNA Framework Members .NET Framework Class Library Gesture Properties Gesture Class See Also Send Feedback Updated: November 2007 The Gesture type exposes the following members.Properties NameDescriptionConfidenceGets the level ...
Source: microsoft.ink

Using a Custom Gesture Recognizer (Windows)
Using a Custom Gesture Recognizer You can use a custom gesture recognizer independently, or in addition to the GestureRecognizer. Create your custom gesture recognizer as an IStylusSyncPlugin ...
Source: TabletandTouch

Gesture Methods (Microsoft.Ink)
Members Include .NET Framework Members Include .NET Compact Framework Members Include XNA Framework Members .NET Framework Class Library Gesture Methods Gesture Class See Also Send Feedback Updated: November 2007 The Gesture type exposes the following members.Methods NameDescriptionEquals Determines whether ...
Source: microsoft.ink

Application Gestures and Semantic Behavior (Windows)
Windows Vista SDK. The Microsoft gesture recognizer is built to recognize these gestures. By default, no gestures are enabled. Applications must choose the gestures to enable. In addition to recognizing gestures, the Microsoft gesture recognizer also provides alternates along with ...
Source: TabletandTouch

InkApplicationGesture Enumeration (Windows)
set the interest in a set of application-specific gesture. Application gestures are gestures that you can choose to have ... enumeration type). This means you can incorporate an application gesture that has a component that may be construed as a ...
Source: TabletandTouch


=========================================================================
Multi Touch
=========================================================================

Intuitive User Experience (Windows)
time, Windows 7 allows developers and their end-users to control their computers by touching the screen. Touch and multi-touch features provide a natural, intuitive way for users to interact with PCs. The developer platform includes high-level gesture ...
Source: Windows7DeveloperGuide

Supporting Pen and Touch Input (Windows)
Supporting Pen and Touch Input Tablet PC users rely on pen and touch input as primary methods of controlling applications and entering information. This section discusses the use ...
Source: MobilPC

Pen and Touch Input in Windows Vista (Windows)
Pen and Touch Input in Windows Vista Windows Vista introduces touch input capability for Tablet PCs that support it, a new cursor scheme to use with the ...
Source: MobilPC

Designing for Touch Input (Windows)
Designing for Touch Input If your users will use touch as a primary way of interacting with your application, consider implementing a user interface that's ...
Source: MobilPC

Touch Input Support in Windows Vista (Windows)
Touch Input Support in Windows Vista Starting with Windows Vista, Tablet and Touch Technology has support for touch input on Tablet PC's with touch capable digitizers ...
Source: TabletandTouch

Touch Members (Microsoft.Build.Tasks)
Members Include .NET Framework Members Include .NET Compact Framework Members Include XNA Framework Members .NET Framework Class Library Touch Members Touch Class Constructors Methods Properties See Also Send Feedback Updated: November 2007 This API supports the .NET Framework infrastructure and ...
Source: microsoft.build.tasks

Touch Class (Microsoft.Build.Tasks)
NET Framework Class Library Touch Class Members See Also Send Feedback Updated: November 2007 This API supports the .NET Framework infrastructure and is not intended to be used directly from your code. Implements the Touch task. Use the Touch element ...
Source: microsoft.build.tasks

Touch Constructor (Microsoft.Build.Tasks)
Code: Visual C++ Code: J# Code: JScript Visual Basic C# Visual C++ J# JScript .NET Framework Class Library Touch Constructor Touch Class See Also Send Feedback Updated: November 2007 This API supports the .NET Framework infrastructure and is not intended ...
Source: microsoft.build.tasks

No Touch Deployment (Windows)
No Touch Deployment Implementation of no-touch deployment of ink-enabled applications from a Web or file server. The Microsoft?.NET Framework gives you ...
Source: TabletandTouch

Optimizing Touch Command and Control (Windows)
Optimizing Touch Command and Control A well-designed Ultra-Mobile PC user interface provides users simple, direct and reliable touch interaction. Design and organize touch targets, such as buttons and links ...
Source: MobilPC

No-Touch Deployment Web Sample (Windows)
No-Touch Deployment Web Sample Description of the No-Touch Deployment sample for the Tablet PC. This sample shows how to deploy a managed Tablet PC ...
Source: TabletandTouch

Touch Task
J# JScript .NET Framework General Reference Touch Task Example See Also Send Feedback Updated: November 2007 Sets the access and modification times of files. Parameters The following table describes the parameters of the Touch task. Parameter Description AlwaysCreate Optional Boolean ...
Source: .NET Framework: General Reference

Touch Properties (Microsoft.Build.Tasks)
Members Include .NET Framework Members Include .NET Compact Framework Members Include XNA Framework Members .NET Framework Class Library Touch Properties Touch Class See Also Send Feedback Updated: November 2007 This API supports the .NET Framework infrastructure and is not intended ...
Source: microsoft.build.tasks

Touch Methods (Microsoft.Build.Tasks)
Members Include .NET Framework Members Include .NET Compact Framework Members Include XNA Framework Members .NET Framework Class Library Touch Methods Touch Class See Also Send Feedback Updated: November 2007 This API supports the .NET Framework infrastructure and is not intended ...
Source: microsoft.build.tasks

2009/01/07

base64 encode 如何把外部的檔放進同一個 html 中?

底下要談的主要是針對 SVG, 但是一般的 HTML 其實也行,只是範例是使用 SVG 來講解而已,請參考SVG 範例, HTML 範例

這邊有講解,並且有示範用 perl 如何完成。之所以能將外部的檔案放在 html / svg 裡,其原理是要先對想包的內容利用 base64 的演算法編碼過,這樣才不會在內容中有特殊字元,例如 ", ', <, >,或一般的控制字元(ASCII < 0x20),而這樣的事是 W3C 制定的標準,因此瀏覽器必須支援.....(不支援的大概就是沒聽過的瀏覽器)

若要轉換,可以參考底下的線上轉換工具,或是安裝 cygwin, 或是在 Linux 下,都有預設的工具,其命令名稱就叫 base64(在 coreutils 套件下):

http://webnet77.com/cgi-bin/helpers/base-64.pl
http://rumkin.com/tools/compression/base64.php
這邊有一個用 javascript 寫的工具,你可以自己寫頁面來轉換, 上面有提到utf-8 的問題,值得大家參考。還有一點參考資料可助理解 base64. 這邊有一個號稱效率更高的演算法,用的是查表法.

SVG 範例裡面,可以看到用法上如下,其中 &si; 其實是個變數,定義在前面

<!ENTITY si 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA'>

<symbol id="Invader1b">
<image width="8" height="8" xlink:href="&si;EAAA...." />
</symbol>
====== 上面相當於 =====>
<symbol id="Invader1b">
<image width="8" height="8" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAA...." />
</symbol>


上面 href="data:image/png;base64, 是型別宣告,若你的內容是 gif, jpg 請改成適當的字串值,後面接著的就是經過 base64 編碼後的內容,通常你用純文字檔檢視即可,複製後再貼上即可。要用 base64 進行轉換相當簡單,譬如把 a.png 編碼成 a.png.base64:
% base64 a.png > a.png.base64
反編碼(解碼)的話如下:
% base64 -d a.png.base64 > a.png

同樣的事若是放在 C/C++ 中呢?可以參考這一篇說的方式去做,這邊的意思是,原來說的是文字檔,其實任何檔都可以看成是文字檔不是嗎?差別只在於你怎麼用而已,而不是在轉換過程。這麼說不是沒根據的,譬如網頁,怎麼傳圖片?譬如 email 怎麼夾帶圖片與影片?我說個最簡單的,你想想看,同樣的內容用 printf() 裡面的 %d, %f, %x, %s 來印,結果是不是不相同?why?

2008/12/16

Windows 7 Touch Digitizer 心得

本文要說明的主要來自微軟的文件

For Windows 7, touch digitizers appear through HID as a touch digitizer (page 0x0D, usage 0x04).
The following usages are required:
• X (page 0x01, usage 0x30) and Y (page 0x01, usage 0x31).
• Contact ID (page 0x0D, usage 0x51).
• Tip switch (page 0x0D, usage 0x42) - 指示出手指是否碰觸到螢幕(Digitizer Surface)
• In-range (page 0x0D, usage 0x32).

關於 z 軸我一直覺得很有用,微軟有一段說明如下:
If the device supports z-axis detection, it reports in-range correctly. If the device does not support z-axis detection, the driver reports packets with in-range and tip switch set when a finger comes in contact with the digitizer.

我試著解釋一下(不保證我的理解正確):
如果有 z 軸值,就放在 In-Range 中,此時 Tip Switch 不必設定。
如果沒有 z 軸值,那麼碰觸時請設定 Tip Switch 及傳回適當的 In-Range 值。
(註: 這一版本與之前的 OS 規範不一樣,如與 XP Tablet PC,請見Windows XP Tablet PC OEM Preinstallation Kit (OPK))

底下的資訊是選擇性的,意思是硬體有支援再提供即可:
• Confidence (page 0x0D, usage 0x47) - 這一點很奇怪,意思是前面的觸控點資訊有可能是意外產生時,可以由裝置設定這個值。
• Width and height (page 0x0D, usages 0x48 and 0x49).

來看看一個 USB HID device report 的 sample:

Here is a sample report descriptor for a touch digitizer device:
0x05, 0x0d, // USAGE_PAGE (Digitizers) 0
0x09, 0x04, // USAGE (Touch Screen) 2
0xa1, 0x01, // COLLECTION (Application) 4
0x85, REPORTID_TOUCH, // REPORT_ID (Touch) 6
0x09, 0x20, // USAGE (Stylus) 8
0xa1, 0x00, // COLLECTION (Physical) 10
0x09, 0x42, // USAGE (Tip Switch) 12
0x15, 0x00, // LOGICAL_MINIMUM (0) 14
0x25, 0x01, // LOGICAL_MAXIMUM (1) 16
0x75, 0x01, // REPORT_SIZE (1) 18
0x95, 0x01, // REPORT_COUNT (1) 20
0x81, 0x02, // INPUT (Data,Var,Abs) 22
0x95, 0x03, // REPORT_COUNT (3) 24
0x81, 0x03, // INPUT (Cnst,Ary,Abs) 26
0x09, 0x32, // USAGE (In Range) 28
0x09, 0x37, // USAGE (Data Valid-Finger) 30
0x95, 0x02, // REPORT_COUNT (2) 32
0x81, 0x02, // INPUT (Data,Var,Abs) 34
0x95, 0x0a, // REPORT_COUNT (10) 36
0x81, 0x03, // INPUT (Cnst,Ary,Abs) 38
0x05, 0x01, // USAGE_PAGE (Generic Desktop) 40
0x26, 0xff, 0x7f, // LOGICAL_MAXIMUM (32767) 42
0x75, 0x10, // REPORT_SIZE (16) 45
0x95, 0x01, // REPORT_COUNT (1) 47
0xa4, // PUSH 49
0x55, 0x0d, // UNIT_EXPONENT (-3) 50
0x65, 0x00, // UNIT (None) 52
0x09, 0x30, // USAGE (X) 54
0x35, 0x00, // PHYSICAL_MINIMUM (0) 56
0x46, 0x00, 0x00, // PHYSICAL_MAXIMUM (0) 58
0x81, 0x02, // INPUT (Data,Var,Abs) 61
0x09, 0x31, // USAGE (Y) 63
0x46, 0x00, 0x00, // PHYSICAL_MAXIMUM (0) 65
0x81, 0x02, // INPUT (Data,Var,Abs) 68
0xb4, // POP 70
0x05, 0x0d, // USAGE PAGE (Digitizers) 71
0x09, 0x60, // USAGE (Width) 73
0x09, 0x61, // USAGE (Height) 75
0x95, 0x02, // REPORT_COUNT (2) 77
0x81, 0x02, // INPUT (Data,Var,Abs) 79
0x95, 0x01, // REPORT_COUNT (1) 81
0x81, 0x03, // INPUT (Cnst,Ary,Abs) 83/85
#ifdef _ CUSTOMVENDORUSAGE _
0x06, 0x00, 0xff, // USAGE_PAGE (Vendor Defined) 0
0x09, 0x80, // USAGE (Vendor Usage 0x80) 3
0x09, 0x81, // USAGE (Vendor Usage 0x81) 5
0x15, 0x00, // LOGICAL_MINIMUM (0) 7
0x27, 0xff, 0xff, 0xff, 0xff, // LOGICAL_MAXIMUM (0xffffffff) 9
0x75, 0x20, // REPORT_SIZE (32) 14
0x95, 0x02, // REPORT_COUNT (2) 16
0x81, 0x02, // INPUT (Data,Var,Abs) 18/20
#endif
0xc0, // END_COLLECTION 0/1
0xc0, // END_COLLECTION 0/1


底下的資訊由微軟提出,隨時有可能修正:









Proposed Additions to the HID Specification to Support Multitouch
Description Page Type Name ID
Contact identifier Digitizer DV (Dynamic Value) Contact identifier 0x51
Configuration Digitizer CA (Collection Application) Configuration 0x0E
Input mode Digitizer DV (Dynamic Value) Input mode 0x52
Device index Digitizer DV (Dynamic Value) Device index 0x53
Actual contact count Digitizer DV (Dynamic Value) Contact count 0x54
Maximum number of contacts supported Digitizer DV (Dynamic Value) Maximum count 0x55


Reporting 模式有三種, 建議採用 Parallel Mode:
• Serial mode: 一次只有一個單一接觸點. 這種模式有可能會改變裝置報告的速度。
• Parallel mode: 每個封包夠寬,足以容納所有接觸
• Hybrid mode: 混合模式可以將前面兩個模式視為它的特例,它擁有固定寬度的封包,卻同時可以擁有多個封包內容。

Parallel Mode 會使用到 Actual contact count 及 Null Value, 底下有個範例,根據 maximum count 及 actual count 的不同可以視為 Parallel Mode 或 Hybrid Mode:

0x05, 0x0d, // USAGE_PAGE (Digitizers)
0x09, 0x04, // USAGE (Touch Screen)
0xa1, 0x01, // COLLECTION (Application)
0x85, REPORTID_PEN, // REPORT_ID (Touch)
0x09, 0x22, // USAGE (Finger)
0xa1, 0x02, // COLLECTION (Logical)
0x09, 0x42, // USAGE (Tip Switch)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x09, 0x32, // USAGE (In Range)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x09, 0x47, // USAGE (Touch Valid)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x05, // REPORT_COUNT (5)
0x81, 0x03, // INPUT (Cnst,Ary,Abs)
0x75, 0x08, // REPORT_SIZE (8)
0x09, 0x51, // USAGE (Contact Identifier)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x05, 0x01, // USAGE_PAGE (Generic Desk..
0x26, 0xff, 0x7f, // LOGICAL_MAXIMUM (32767)
0x75, 0x10, // REPORT_SIZE (16)
0x55, 0x00, // UNIT_EXPONENT (0)
0x65, 0x00, // UNIT (None)
0x09, 0x30, // USAGE (X)
0x35, 0x00, // PHYSICAL_MINIMUM (0)
0x46, 0x00, 0x00, // PHYSICAL_MAXIMUM (0)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x09, 0x31, // USAGE (Y)
0x46, 0x00, 0x00, // PHYSICAL_MAXIMUM (0)
0x81, 0x02, // INPUT (Data,Var,Abs)
0xc0, // END_COLLECTION
0xa1, 0x02, // COLLECTION (Logical)
0x05, 0x0d, // USAGE_PAGE (Digitizers)
0x09, 0x42, // USAGE (Tip Switch)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x09, 0x32, // USAGE (In Range)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x09, 0x47, // USAGE (Touch Valid)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x05, // REPORT_COUNT (5)
0x81, 0x03, // INPUT (Cnst,Ary,Abs)
0x75, 0x08, // REPORT_SIZE (8)
0x09, 0x51, // USAGE ( Temp Identifier)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x05, 0x01, // USAGE_PAGE (Generic Desk..
0x26, 0xff, 0x7f, // LOGICAL_MAXIMUM (32767)
0x75, 0x10, // REPORT_SIZE (16)
0x55, 0x00, // UNIT_EXPONENT (0)
0x65, 0x00, // UNIT (None)
0x09, 0x30, // USAGE (X)
0x35, 0x00, // PHYSICAL_MINIMUM (0)
0x46, 0x00, 0x00, // PHYSICAL_MAXIMUM (0)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x09, 0x31, // USAGE (Y)
0x46, 0x00, 0x00, // PHYSICAL_MAXIMUM (0)
0x81, 0x02, // INPUT (Data,Var,Abs)
0xc0, // END_COLLECTION
0x05, 0x0d, // USAGE_PAGE (Digitizers)
0x09, 0x54, // USAGE (Actual count)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x08, // REPORT_SIZE (8)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x27, 0x08, // LOGICAL_MAXIMUM (255)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x09, 0x56, // USAGE(Maximum Count)
0xb1, 0x02, // FEATURE (Data,Var,Abs)
0xc0, // END_COLLECTION


Top-Level Collection 每個裝置一定要有此描述內容,至少要指出來裝置是單點輸入、多點輸入或是滑鼠。

Collection Applications (CAs) 值對應的裝置若為底下的值,均可以用來做多點輸入:
Digitizer - 1
Pen - 2
Touch Screen - 4
Touch Pad - 5


多點觸控裝置應該在 top-level collections中採用 Finger (0x22) CL (Collection Logical) 來裝 data 及控制訊息。

多觸控裝置的尋找與組態能力:
尋找是透過 report descriptor 裡的 input mode 完成,也應該允許作業系統重新規劃成 multi-input, single-input, or mouse top-level collection。為了系統安全考量,此項 report descriptor 只允許作業系統存取,不開放第三方應用程式存取。這一點跟舊的 Vista 或 XP, 2000 都不一樣,舊的作業系統允許第三方應用程式透過 feature report 重設裝置為 single touch or the mouse。

Feature Report Requirements
所有裝置都需要一個 feature report 在其 report descriptor 中,以便報告裝置的組態。底下來看個實例:

0x06, 0x0d // USAGE_PAGE (Digitizer)
Ox09, 0x0E // USAGE (Configuration)
0x85, REPORTID_FEATURE, // REPORT_ID (Feature)
0xa1, 0x01, // COLLECTION (Application)
0x09, 0x52, // USAGE (Input Mode)
0x09, 0x53, // USAGE (Device Index)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x27, 0x08, // LOGICAL_MAXIMUM (255)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x02, // REPORT_COUNT (2)
0xb1, 0x02, // FEATURE (Data,Var,Abs)
0xc0, // END_COLLECTION


Input Mode的值有:



Mode Value
Mouse (recommended default) 0x00
Single-input (single touch or stylus) 0x00
Multi-input 0x02

所以,多觸控點裝置是可以被重新設定成單一輸入裝置的,此時要表現的如作業系統所期望才行,而且微軟建議所有的多觸控裝置都預設採用 Mouse Mode。

Device Index
The device index usage selects the top-level collection to configure. A value of 0 tells the device to change the mode for every multi-input top-level collection in its report descriptor. A value of 1 and higher indicates the position of the top-level collection in the report descriptor. Applications that use values other than 0 must correctly handle the positions of the multi-input top-level collections in the report descriptor.

參考文獻:
  1. Device Class Definitions for Human Interface Devices (HID)
  2. HID Usage Tables

2008/12/08

Introduction to InterProcess Communication IPC 簡介

探討 IPC 的文章與文件相當多,例如 http://www.linuxhq.com/guides/LPG/node7.html, http://ai.ee.ccu.edu.tw/os/projects/2004fall/ipc_11/os-3.ppthttp://www.comms.scitech.susx.ac.uk/fft/computer/ipc.pdf是兩篇我覺得寫的很棒的文件,當然不是我寫的。

這邊畫蛇添足地說明一下,正常情況下,OS 為了保護每個 Process 的獨立性,不止從 User 來切割整個作業環境,而且也從 Process 來切割,意思是,每個 User 間是獨立的,互相不會影響,不會因為甲用戶惡搞當機而造成乙用戶也跟著當機,當然行程也是如此。這就導致行程間要互相溝通必須做到一件事:

透過 Kernel!

是可以自行利用 file lock 來溝通,但是這也會有問題,例如別人是否也想這麼做?同步問題怎麼解決?附件有提到幾種正規的作法我就不多談,只是要強調出來,正規作法,其實都是透過 kernel 來達成的。因此有必要對 Kernel 提供的機制進行瞭解,包括 Pipe, Name Pipe, Socket, 信號、共享記憶體等等作法都是如此。

事實上 Kernel 提供出來的機制除了 system call 外,還有其他作法,例如 /proc filesystem, 不過這一點有機會再來說明,這邊簡單的說一下,很多情況下,不止是 Process 間要溝通,連裝置間或是裝置與 Process 間要溝通,透過 /proc filesystem 是非常方便的,甚至比 ioctl 來得簡易。但是簡易不代表有效率。當然這作法有一種限制,你必須去改 kernel, 但是若你剛剛好是作嵌入式系統,必須動到 Kernel , 那麼順便修改並提供利用 /proc filesystem 來溝通的機制也是相當方便的。

/proc, /sys 等,都透露出 kernel 愈來愈 Open, 學習是值得的。


Best Regards
--
自由的精靈, 狂想的空間
Free Spirit, Fantasy Space
Marie von Ebner-Eschenbach  - "Even a stopped clock is right twice a day."

2008/12/02

Open Source 法律問題

想知道你的程式中,用了多少 Open Source 的片斷嗎?有一種暴力搜尋法軟體可以用,但是在說明之前先來回答一個問題,我猜會有人問「既然是 Open Source, 怎麼還會有法律問題」?答案其實很明顯,Open Source 所 Open 的是 Source, 並非智慧,也就是軟體並非免費,而是無價(ps:中文就是棒)。

台灣的自由軟體鑄造場裡頭還有工具可以幫你決定要採用哪一種授權,這邊直接回到主題:

http://www.blackducksoftware.com/ 上面問題的答案。
http://www.palamida.com/ 還可以幫你買保險,讓產品減少授權爭議的損失
http://fossology.org/ HP 丟出來的開源軟體

2008/11/24

應用程式間的通訊 RegisterWindowMessage

本文在說明的主要是針對「應用程式間的通訊」這一需求而來。可參考的文章有:

VC++ Example Capture Print Screen to Clipboard including dropdown menu, SetWindowsHookEx and UnhookWindowsHookEx, with RegisterWindowMessage


RegisterWindowMessage, WM_USER, VC++ MFC Example

RegisterWindowMessage Function
Using Common Dialog Boxes
FINDMSGSTRING Notification

第一個參考資料有 source code,這篇心得主要是針對研究此一 source code 而得。我們先不管整個程式到底在幹嘛,只需要知道訊
息是怎麼傳送的。

首先,在 HScr2Clpbrd_DLL\HScr2Clpbrd_DLL.cpp 有一行:
::PostMessage(hWndReceiver,UWM_ClickPrnScrn,0,0);

可以想像到一件事,我用中文來說,這個 DLL 的功用是:
截取鍵盤事件,若偵測到使用者按 PrintScreen 這個按鍵時,就發出我們註冊的事件:
UWM_ClickPrintScreen_B2ABC742-0A63-49c3-9ACB-CF0068027A66

那麼,是怎麼註冊的?在前面,透過下面這行,要知道的是 UWM_ClickPrnScrn 這個變數意義不大,別被搞混了:
UWM_ClickPrnScrn = ::RegisterWindowMessage
("UWM_ClickPrintScreen_B2ABC742-0A63-49c3-9ACB-CF0068027A66");

好啦,兩行解決發送,那麼接收呢?在上一層 HScr2ClpDlg.cpp 這個主程式中:
也是兩行,一行也是註冊訊息,其實是一模一樣的先註冊:
UWM_ClickPrnScrn = ::RegisterWindowMessage
("UWM_ClickPrintScreen_B2ABC742-0A63-49c3-9ACB-CF0068027A66");

接下來就是接收:
ON_REGISTERED_MESSAGE(UWM_ClickPrnScrn, OnClickPrintScreen)

就這樣子啦,真的是夠簡單了。真正比較重要的是上面那個自訂的訊息,是可以自己定義的字串,重點是別人要知道它的內容是什麼,才有辦法接收到你傳出來的
訊息,而且又要盡量獨特,以免跟其他訊息衝突到:
UWM_ClickPrintScreen_B2ABC742-0A63-49c3-9ACB-CF0068027A66

PS: 這個程式還展示了怎麼截收鍵盤按鍵,是值得學習的
PS2: 微軟有非常多自訂的訊息,其中像 Find & Replace 中用的就是 RegisterWindowMessage

2008/11/15

網頁也能動態載入 Javascript 嗎--續2

直接貼範例,說明在範例中

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>test eval</title>
<script type="application/javascript" src="mtm.js"></script>
<script type="application/javascript" src="net.js"></script>
<script>

var extJS = [
{ name: "smile", file: "smile.js", },
{ name: "dance", file: "dance.js" },
];

var Objs = new Array(); // In my mind, this will not know length now.
var msg;

function Ext(obj) {
this.obname = obj.name;
this.file = obj.file;

// use net.ContentLoader() to load external javascript file
this.load = function() {
msg.innerHTML += "<P>Loading " + this.file;
var ajax = new net.ContentLoader(this.file, this.onload, null, 'GET', this.obname);
}

// when loaded, use mtm.insertJS() to insert into document
// 注意,此時已經離開本物件範例而是回到 net.ContentLoader() 的範圍,所以
// 才會是使用 this.id, 而非 this.obname, 故意取不同名稱以便識別
this.onload = function() {
mtm.insertJS(this.req.responseText);

// use eval to "new" object which defined in ext js
eval('Objs['+Objs.length+'] = new '+this.id +'("wade");');
msg.innerHTML += "<P>"+Objs[Objs.length-1].show();
}
}

function init()
{
msg = document.getElementById('msgbar');
msg.innerHTML = "";
for (var i=0; i<extJS.length; i++) {
(new Ext(extJS[i])).load();
}
}
</script>
</head>
<body onload="init()">
<div id=msgbar>Waiting......</div>
</body>
</html>

// smile.js
function smile(name)
{
this.show = function () {
return name + ' smile :-)';
}
}

// dance.js
function dance(name)
{
this.show = function () {
return name + ' dance happily';
}
}

網頁也能動態載入 Javascript 嗎--續

上一篇網頁也能動態載入 Javascript 嗎?雖然也算動態載入,但是它無法等到正式取得之後(或是失敗)再處理,因此會有已經下命令取得外部檔,卻還沒載入完成。這是標準的 Ajax 的問題,就用 Ajax 的方式來解決。底下是另一個 mtm.js 及 net.js, 我本來的設計就是物件化的,內容如下,至於範例另外再寫一篇:


// mtm.js
function MTM()
{
this.import = function(path) {
var i, base="";
var src = 'mtm.js';
var scripts = document.getElementsByTagName("script");
var hadExisted = false;
path = path.replace(/\./g, "/") + '.js';
for (i=0; i<scripts.length; i++) {
if (scripts[i].src.match(src)) {
base = scripts[i].src.replace(src, "");
}
if (scripts[i].src.match(path)) {
hadExisted = true;
}
}
if (!hadExisted) {
document.write("<" + "script src=\"" + base + path + "\"></" + "script>");
}
}
this.insertJS = function(js) {
var scripts = document.getElementsByTagName("script");
var scr = document.createElement("script");
scr.innerHTML = js;
document.body.appendChild(scr);
}
}
var mtm = new MTM();


// net.js
var net=new Object();

net.READY_STATE_UNINITIALIZED=0;
net.READY_STATE_LOADING=1;
net.READY_STATE_LOADED=2;
net.READY_STATE_INTERACTIVE=3;
net.READY_STATE_COMPLETE=4;


/*--- content loader object for cross-browser requests ---*/
net.ContentLoader=function(url,onload,onerror,method,id,params,contentType){
this.req=null;
this.onload=onload;
this.id = id;
this.onerror=(onerror) ? onerror : this.defaultError;
this.loadXMLDoc(url,method,params,contentType);
}

net.ContentLoader.prototype.loadXMLDoc=function(url,method,params,contentType){
if (!method){
method="GET";
}
if (!contentType && method=="POST"){
contentType='application/x-www-form-urlencoded';
}
if (window.XMLHttpRequest){
this.req=new XMLHttpRequest();
} else if (window.ActiveXObject){
this.req=new ActiveXObject("Microsoft.XMLHTTP");
}
if (this.req){
try{
var loader=this;
this.req.onreadystatechange=function(){
net.ContentLoader.onReadyState.call(loader);
}
this.req.open(method,url,true);
if (contentType){
this.req.setRequestHeader('Content-Type', contentType);
}
this.req.send(params);
}catch (err){
this.onerror.call(this);
}
}
}


net.ContentLoader.onReadyState=function(){
var req=this.req;
var ready=req.readyState;
if (ready==net.READY_STATE_COMPLETE){
var httpStatus=req.status;
if (httpStatus==200 || httpStatus==0){
this.onload.call(this);
}else{
this.onerror.call(this);
}
}
}

net.ContentLoader.prototype.defaultError=function(){
alert("error fetching data!"
+"\n\nreadyState:"+this.req.readyState
+"\nstatus: "+this.req.status
+"\nheaders: "+this.req.getAllResponseHeaders());
}

2008/11/12

怎樣讓 shell script 把自己丟入背景?

這議題似乎不怎麼吸引人,原文來自這兒

sub shell 的意思,就是把某個片斷的 shell script 擺在 () 內,裡面的運作是獨立的,含 shell 環境變數。不過別搞錯我的意思,前句話的意思是說,sub shell 裡頭的變數不會讓外面的看到,卻看得到外面的變數。若有興趣的話,可以見比較完整的說明及範例