Sean's Note: 2012

2012年12月29日 星期六

Primitive type & Reference type

在 Java 裡,型別被分為兩大類 Primitive type 和 Reference type,

有八個型別屬於 Primitive type,分別是 boolean, char, byte, short, int, long, float, double,

其他如 String, Array 和使用者自定義的 class 則屬於 Reference type。

而兩者重要的差別在於,當變數被當作函式的參數傳遞時,

Primitive type 的值不因函式運算而改變。

Reference type 的值會因函式運算而改變 (除了 String 以外!)。

大多人會覺得那這不就是 C++ 中的 call by reference 嗎?

其實都是 call by value,因為 Java 不允許處理記憶體位置。

 (詳見: http://openhome.cc/Gossip/JavaEssence/CallByValue.html)。

String 雖然是 Reference type,但在函式裡更改其值,並不影響外部變數的結果,

這是因為 str = "Hello" 等同於 str = new String("Hello"),str 指向了新的記憶體空間,

所以不會更動到原本的記憶體。

2012年12月28日 星期五

[Eclipse] Getting error when importing existing android code into workspace.

在 Eclipse 裡 "Import" -> "Existing Android Code Into Workspace" 時,出現了如下圖的

錯誤訊息 :

Invalid project description
原因是我把 source 來源也放在 workspace 裡,解決的方法有兩個:
  1. 勾選 "Copy projects into workspace"。
  2. 把 source 放到其他地方不要放在 workspace 裡,然後再 import 一次。(不過這樣 project 會放在 workspace 外面)。

2012年12月18日 星期二

用 Java 讀取 HTTP 網頁內容

在 JDK 的 java.net 包中已經提供了訪問 HTTP 協定的基本功能:HttpURLConnection。

Apache 也提供了對應的 HttpClient 功能更為強大也更容易使用。

HttpURLConnection 與 HttpClient 的比較可參考這篇文章 :

http://superonion.iteye.com/blog/1545496

而下面是個完整可執行的程式碼,用來讀取 Apache 的網頁資訊 :

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

// Using version 4.2.2
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;

public class HttpClientSample{
    public   static   void  main(String[] args) throws ClientProtocolException, IOException {
     DefaultHttpClient  httpClient = new DefaultHttpClient();
    
     // Prepare a request object
     HttpGet httpget = new HttpGet("http://www.apache.org/");

     // Execute the request
     HttpResponse response = httpClient.execute(httpget);

     // Examine the response status
     System.out.println(response.getStatusLine());

     // Get hold of the response entity
     HttpEntity entity = response.getEntity();
     System.out.println(entity.getContentType());
     
     //System.out.println(EntityUtils.toString(entity));
     // If the response does not enclose an entity, there is no need
     // to worry about connection release
     if (entity != null) {
         InputStream instream = entity.getContent();
         try {
             BufferedReader reader = new BufferedReader(new InputStreamReader(instream));
             // do something useful with the response
             String str;
             while (reader != null && (str = reader.readLine()) != null)
             {
              System.out.println(str);
             }
             
         } catch (IOException ex) {

             // In case of an IOException the connection will be released
             // back to the connection manager automatically
             throw ex;

         } catch (RuntimeException ex) {

             // In case of an unexpected exception you may want to abort
             // the HTTP request in order to shut down the underlying
             // connection and release it back to the connection manager.
             httpget.abort();
             throw ex;

         } finally {
             // Closing the input stream will trigger connection release
             instream.close();

         }
     }
    }
}

2012年12月11日 星期二

[Android] 印出 JavaScript 的 log

我們都知道在網頁開發中,在 JavaScript 裡打上 console.log() 就可以用 Tools 看 log,
同樣的,在開發 Android 1.6 以下的 Web Apps 時,用 console.log() 也可以將 log 印在
Eclipse 端的 LogCat 或手機端的 aLogcat。 在 Android 2.1 (API Level 7) 以上,則必須實做
WebChromeClient 並 override onConsoleMessage() callback 方法。

(詳見: Android Developers)

實測案例:
1. Samsung Galaxy R (Android 4.0.4):  console.log() 無用,必須 override callback 方法。
2. Toshiba AT500 (Android 4.0.3):  console.log() 可直接印出 Tag 為 Console Web 的訊息。

Note:
  1.  AT500 安裝 ADB USB Driver 的方法
  2. 手機上的 aLogcat, CatLog 等 App,因為新的安全政策,已無法在
    Android 4.1 (Jelly Bean) 上的裝置印出 log,除非 root 過,詳見


2012年12月5日 星期三

在 JavaScript 中常用的 bind 方法

有時候我們會頻繁的使用某個 Object 底下的函式,

於是不斷的呼叫 Object.func() ...

我們可以利用 bind 技巧的實現,省去一些程式碼的撰寫。

bind 顧名思義,就是將某個 object 和函式綁定在一起。

範例如下:

function bind(object, func)
{
  return function()
   {
      return func.apply(object, arguments);
   };
}

var testArray = [];
var pushToTest = bind(testArray, testArray.push);

pushToTest("A");
pushToTest("B");
show(testArray); // ["A", "B"]

2012年12月3日 星期一

Android's dialog 選項與 Index 的關係

在建立 Dialog 時,很常見對 Positive/Negative 按鈕,用匿名內層類別 (Anonymous Inner Classes)
的方式各別對其建立 OnClickListener 物件。另外一種寫法是,不管使用者按下哪個選項,
都用同一個 OnClickListener 物件,在依據 int which 參數來判斷是哪個選項。

Positive Button 為 -1
Negative Button 為 -2
Neutral Button 為 -3

Items 則從 0 開始遞增
範例如下:

...

String[] options = {"紅色", "黃色", "綠色" };
builder.setItems(options, listener); // 指定選項
builder.setPositiveButton("確定", listener);
builder.setNegativeButton("取消", listener);
builder.setNeutralButton("設定", listener);

DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener(){
  public void onClick(DialogInterface dialog, int which) {
    // 找到Button元件
    Button btn = (Button) findViewById(R.id.button1);
    // 指定背景色彩
    switch(which){
      case -3:
        // Neutral 選項被按下
        break;
      case -2:
        // Negative 選項被按下
        break;
      case -1:
        // Positive 選項被按下
        break;
      case 0:
        btn.setBackgroundColor(Color.RED);
        break;
      case 1:
        btn.setBackgroundColor(Color.YELLOW);
        break;
      case 2:
        btn.setBackgroundColor(Color.GREEN);
        break;
    }   
  }
};

...


▲ 各選項的 Index 

2012年11月29日 星期四

[JavaScript] function 函數

JavaScript 的 function 與 C/C++ 不同的地方有三點:

1. function 可被定義在另一個 function 裡
function MakeMulFunction(amout)
{
  function Mul(number)
  {
    return number*amout;
  }
  return Mul;
}

2. 允許匿名函式 (Anonymous Function)
function MakeMulFunction(amout)
{
  return function (number)
  {
    return number*amout;
  }
}

3. 可用變數來定義 function (類似 C/C++ function pointer 的功能)
var Add = function(a, b) { return a+b; };

2012年11月27日 星期二

安裝 Aptana Studio 3

Aptana Studio 3 是一套支援網頁開發的外掛程式,支援大部分的網頁語言編輯撰寫功能,

如 HTML、PHP、JavaScript、Rails、Python 等。而除了程式碼提示、自動完成與偵錯的功能,

也提供了一些程式碼的佈景主題,讓程式碼更容易閱讀。

在 Eclipse 安裝 Aptana Studio 3 的套件時,如果曾經裝過 PyDev 套件,

會出現和 Aptana 和 PyDev 相衝的錯誤訊息,因為 Aptana Studio 3 裡已包含 PyDev 套件,

所以可先移除 PyDev 套件再重新安裝一次即可。


在 2014.8.22 補充:

最近更新 Aptana 3.6 後,PyDev 在 theme 和 auto completion 上都變得怪怪的

後來乾脆只裝 PyDev 3.6,自己改 PyDev Editor 的 Color 設定。

XML 則裝 Rinzo XML Editor 1.4: http://editorxml.sourceforge.net/updates/。

2012年11月14日 星期三

JPG, EXIF 與 Orientation

JPEG, TIFF 或 RIFF 中會有個 EXIF (Exchangeable image file format) 標頭檔,

裡面存放了許多資訊,例如: 製造廠商 (Manufacturer)、相機型號 (Model)、

影像方向 (Orientation)、光圈值 (FNumber) 與 ISO 等等。其中,Orientation 是為了數位相機

和手機等所使用,記錄使用者拍照時相機的方向,以八個值定義:

1 - 右上 (我們平常拿相機的方向,若以右上角的拍照鍵定為基準點),此時人頭朝上
2 - 1 的左右鏡像
3 - 左下 (基準點此時在右下),此時人頭朝下
4 - 3 的左右鏡像
5 - 6 的左右鏡像
6 - 右下,此時人頭朝左
7 - 7 的左右鏡像
8 - 左上,此時人頭朝右

以 1, 3, 6, 8 為常見值,2, 4, 5, 7 除非顯示裝置或軟體支援,否則無效。

Windows Photo Viewer 並不支援 EXIF 的 Orientation Flag,也就是說原始資料 (Raw Data)

是什麼就顯示什麼,並不會幫使用者轉方向。另外,使用 Windows Photo Viewer 轉向後

儲存也會造成失真,建議還是以其他軟體來編輯相片吧!


參考資料:
  1. http://en.wikipedia.org/wiki/Exchangeable_image_file_format
  2. http://www.impulseadventure.com/photo/exif-orientation.html

2012年10月31日 星期三

利用 WM_GESTURE 寫出有 Touch 功能的程式

如果只想做出簡單的 PAN 功能,可透過接收 WM_TABLET_FLICK 訊息來達成,

其提供了八個方向,但在 Win8 上好像收不到這個訊息。

另外的替代方案是,在 Win7 以上的作業系統,我們可以透過接受 WM_GESTURE 來實作。

在使用前先透過 WM_GESTURENOTIFY 和 SetGestureConfig() 設定我們要或不要接收

哪些手勢。假如設定好只接受 PAN 的手勢後,即可在 WM_GESTURE 用 GetGestureInfo()

攔到 GESTUREINFO.dwID = GID_PAN 的資訊。

另外由 GESTUREINFO.dwFlags = GF_BEGIN/GF_INERTIA/GF_END 來分析起始點、慣性點和

終點。要注意的是,除非有明確的 PAN 動作(手指離開時的點需停留得夠久),否則

GF_BEGIN/GF_END 並不會成對出現,而會出現 GF_INERTIA 的慣性點。

GF_INERTIA 是用來實作像是拖曳卷軸時手已經放開的滑動效果。

2012年10月24日 星期三

改變 TextOut 時的字型或大小

我們可以利用 CreateFont() 和 CreateFontIndirect() 來產生 HFONT 物件。

hFont = 

CreateFont(48,0,0,0,FW_DONTCARE,FALSE,TRUE,FALSE,DEFAULT_CHARSET,OUT_OUTLIN 

E_PRECIS, CLIP_DEFAULT_PRECIS,CLEARTYPE_QUALITY, 

VARIABLE_PITCH,TEXT("Impact")); 

然後再將此字型物件置換到 DC 上即可。

SelectObject(hDC, hFont);

TextOut(hDC, 0, 0, "Hello", lstrlen("Hello"));

Ref: http://msdn.microsoft.com/en-us/library/windows/desktop/dd183499(v=vs.85).aspx

畫出只有邊框的透明 Rectangle

我們只要在選擇筆刷時設 NULL_BRUSH 即可 :

SelectObject(hDC,GetStockObject(NULL_BRUSH));

Rectangle(hDC, 0, 0, 100, 100);

[STL] 位移 List 的 Iterator

平常我們會使用 List 來記錄一些 data,例如:
list<int> mylist;

for (int i=0; i<10; i++) mylist.push_back (i*10);

並將 Iterator 指向開頭來走訪 data。

list<int>::iterator it = mylist.begin();

想要取得下一個元素時,可以使用 *it++ 前進一步。


那想要取得第 N 個元素呢?


呼叫 *it++ N 次嗎?


於是我們有了 advance 函式幫我們快速的移動到第 N 個元素:

advance (it, N-1);

2012年10月21日 星期日

[Windows] 開機時讓 Num Lock 鍵預設為開啟

Windows 開機時 Num Lock 鍵預設是關的,想要打開可以透過 Regedit.exe 來達成。

找到 HKEY_USERS\.DEFAULT\Control Panel\Keyboard\InitialKeyboardIndicators, 

把值改為 2 即開啟,0 為關閉。

2012年8月22日 星期三

程式相容性助理

在 Win7 或 Win8 上常常可以看到一些程式直行或關閉時,跳出程式相容性助理
(Program Compatibility Assistant) 的視窗,跳出的原因有很多種可以參考這篇,
http://msdn.microsoft.com/library/bb756937.aspx。若想透過程式的方法強制把 PCA 關掉,
可以在開發程式時的 Manifest 檔加上一些屬性,詳細可參考:
http://msdn.microsoft.com/en-us/library/windows/desktop/dd371711(v=vs.85).aspx 。

2012年8月13日 星期一

[Win8] 以檔案開啟...

在 Win8 裡第一次執行文件或檔案時,會跳出你要用哪種檔案來開啟的小視窗,此時該檔案右

側的文字所顯示的即是檔案的描述(File Description)。在用 Visual Studio 開發 Windows App 時,

可從 Resource View 裡,找到專案的 Version\VS_VERSION_INFO 資源檔去做更改。

同時,這個值會被 cache 在 :


Path: HKEY_CLASSES_ROOT\Local Settings\Software\Microsoft\Windows\Shell\MuiCache

Name: C:\Windows\system32\mspaint.exe.FriendlyAppName

Data: Paint






2012年6月27日 星期三

[USB2.0] PNY Key Attache 16GB

PNY Key Attache 極致纖薄Q版鑰匙造型隨身碟16GB
PNY Key Attache 16GB













最近在 Y 購物上買了這款便宜的隨身碟 NT.259,拿到後

馬上格式化成 NTFS 16K,再用 CrystalDiskMark 3.0.1 跑效能測試,

發現讀的速度還不錯 23MB/s,不過寫也太爛了,只有 4.7MB/S,

感覺是平均市售隨身碟的一半速度...

果然還是一分錢一分貨阿!

不過這也不一定準,

實際存 2~3 G 的檔案時跑到 100M~20M 左右還不錯,

但存幾百M但檔案都很小又多時,速度還會掉到幾十 K...

評測結果

2012年6月26日 星期二

不要將 vector 做為參數傳遞至 DLL

最近用了 STL 的 vector 當作 DLL 裡的函式參數,讓 EXE 建立的 vector 給 DLL 做事,

結果發現一直莫名其妙的 Crash,原來 EXE 和 DLL 會有各自的記憶體存放靜態成員,

而大部分的 STL 物件類別都使用靜態成員資料(Static Data Member),所以就會造成 


Access Violation, Data Lost 甚至於 Crash。


參考資料:
http://www.cnblogs.com/mysunnyday/archive/2011/08/23/2150279.html
http://support.microsoft.com/default.aspx?scid=KB;en-us;q172396

2012年6月20日 星期三

[MFC] 將使用者設定儲存到 Key 裡

通常一個較好的使用者介面,會在程式關閉時,將使用者的狀態紀錄到系統裡,

等下次使用者開啟軟體時,再將狀態讀出,顯示使用者關閉前的狀態,

而我們可以透過幾個 Windows API 做到這樣的功能。

CWinApp::GetProfileInt
CWinApp::GetProfileString
CWinApp::WriteProfileInt
CWinApp::WriteProfileString

原本這些 API 會將狀態寫到 C:\Windows\XXX.INI 裡,也從這裡讀,

但在 MSDN 上已說這不是個好的方式,建議存放到 Registry Key 裡。


透過 SetRegistryKey(LPCTSTR lpszRegistryKey) 可以指定存放到 Registry Key 而非 INI 檔。


存放的路徑如下:
HKEY_CURRENT_USER\Software\<company name>\<application name>\<section name>\<value name>.


其實 SetRegistryKey 就是把 CWinAp::m_pszProfileName 成員變數設成你所設定的值,

否則預設是 XXX.INI。


注意: 如果是用 Win32 API 的 WriteProfileString 寫到的則是 C:\Windows\win.ini 裡。



2012年6月16日 星期六

[C/C++] public/protected/private 繼承

class A
{
      public:
      void print() {printf ("print() From class A\n");};
      protected:
      void print2() {printf ("print2() From class A\n");};
      private:
      void print3() {printf ("print3() From class A\n");};
      
};

class PublicB : public A
{
      public:
      int print() {printf ("print() From class B\n"); print2();};  // Redefine
      /* 注意: protected 的 print2() 雖被繼承下來, 但不為外人所用 */
      /* 注意: private 的 print3() 並沒有被繼承下來 */
};

class ProtectedB : protected A
{
      public:
      /* 注意: public 的 print() 雖被繼承下來, 但此時已變為 protected */
      /* 注意: protected 的 print2() 雖被繼承下來, 但不為外人所用 */
      /* 注意: private 的 print3() 並沒有被繼承下來 */
};

class PrivateB : private A
{
      public:
      void myPrint() {print(); print2();};      
      /* 注意: public 的 print() 雖被繼承下來, 但此時已變為 private */
      /* 注意: protected 的 print2() 雖被繼承下來, 但此時已變為 private */
      /* 注意: private 的 print3() 並沒有被繼承下來 */
};

int main()
{
    A clsA;
    clsA.print();
    //clsA.print2(); // Compiler Error! print2() is protected.
    
    PublicB clsB_pub;
    clsB_pub.print();
    //clsB_pub.print2(); // Compiler Error! print2() is protected.
    
    ProtectedB clsB_pro;
    //clsB_pro.print(); // Compiler Error! print() is protected.
    //clsB_pro.print2(); // Compiler Error! print2() is protected.
    
    PrivateB clsB_pri;
    clsB_pri.myPrint();

    system("pause");
}
  1. 首先,繼承的概念是,只有 public 和 protected 的成員函式或變數會被繼承下來,除了建構式 (Constructor)、解構式 (Constructor) 和 Copy Constructor 除外,還有 private 也不會。
    • public: 所有人都能使用。
    • protected: 只有自己和兒子 (Derived Class) 可以使用,外人不能使用。
    • private: 只有自己可以使用, 兒子 (Derived Class) 和外人皆不能使用。
  2. 倘若 B 以 public 方式繼承了 A,則存取修飾字 (Access Specifier) 保持相同,規則同 1。
  3. 倘若 B 以 protected 方式繼承了 A,則 A 的 public 和 protected 成員被以 protected 方式繼承,所以範例中的 Line:48, 49 則發生編譯錯誤,因為  protected 成員不為外人所用。
  4. 倘若 B 以 private 方式繼承了 A,  則 A 的 public 和 protected 成員被以  private 方式繼承 ,僅自身可使用 Line:31。

2012年6月8日 星期五

在 Google Blogger 中使用 SyntaxHighlighter 3.0.83

有時候想貼出美美的程式碼,卻不知道怎麼用,

在網路上發現了 SyntaxHighlighter 這個工具,支援 C、C++、Python、HTML、CSS 等等。

教學文章:
http://sharedderrick.blogspot.tw/2010/10/google-blogger-syntaxhighlighter-3083.html

不過並沒有提供 Objective-C 的支援,好在有熱心人士寫了一份放在 GitHub 上:

https://github.com/scottdensmore/ObjectiveCSyntaxHighlighter

Windows 7 電腦每天會在特定時間無預期的從睡眠狀態中喚醒

發現電腦休眠後,常常還是莫名的被喚醒。

後來才發現是 Media Center 在作怪。

http://support.microsoft.com/kb/979878/zh-tw

2012年6月7日 星期四

class 中的 const 成員函式

const 函式主要定義為不能改變 class 中的變數。
此外,const  物件 只能引用 const 函式。


class A
{
private:
      int number;
public:
      A(int value){number=value;};
      void const_f(void) const {/*number=1;*/}; // 不能對成員變數賦值
      void nonconst_f(void){number=1;};
};

int main()
{
    const A a(1);
    a.const_f();
    a.nonconst_f(); // 編譯錯誤: const 物件只能引用 const 函式
    return 0;  
}

2012年6月5日 星期二

把視窗移到最前面

試過了 BringToTop() 和 SetWindowsPos() 都沒什麼用。

SwitchToThisWindow() 有用,但不是想要的效果。

SetForegroundWindow() 有用,但不是每次都成功,

失敗時程式就會在工作列上閃阿閃的 (註 1)。

最後參考了這篇的第二段 code ,終於實現了需要的功能:
http://www.codeproject.com/Tips/76427/How-to-bring-window-to-top-with-SetForegroundWindo

最主要是 AttachThreadInput() 讓 SetForegroundWindow() 幾乎都能成功。


註 1: 利用 SPI_SETFOREGROUNDFLASHCOUNT 可以控制要閃的次數。
SystemParametersInfo( SPI_SETFOREGROUNDFLASHCOUNT, 0, 5, SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE);

2012年4月9日 星期一

Windows 常用快捷建


F1           顯示當前程式或者windows的輔助內容。 
F2           當你選中一個文件的話,這意味著“重命名” 
F3           當你在桌面上的時候是開啟“尋找:所有文件” 對話方塊 

DELETE        刪除被選擇的選擇檔案,如果是文件,將被放入資源回收桶 
SHIFT+DELETE       刪除被選擇的選擇檔案,如果是文件,將被直接刪除而不是放入資源回收桶 
CTRL+N        新建一個新的文件 
CTRL+O        開啟“開啟文件”對話方塊 
CTRL+P        開啟“列印”對話方塊 
CTRL+S        儲存當前操作的文件 
CTRL+X        剪切被選擇的檔案到剪貼簿 
CTRL+C                             複製被選擇的檔案到剪貼簿 
CTRL+V                             貼上剪貼簿中的內容到當前位置 
CTRL+Z                                取消上一步的操作 
  
Windows鍵+M      最小化所有被開啟的視窗。 
Windows鍵+E       開啟我的電腦 
Windows鍵+R       開啟“執行”對話方塊 
Windows鍵+BREAK     開啟“系統屬性”對話方塊 

SHIFT+F10或滑鼠右擊    開啟當前活動檔案的快顯功能表 
SHIFT         在放入CD的時候按下不放,可以跳過自動播放CD。
ALT+F4         關閉當前應用程式 
ALT+SPACEBAR       開啟程式最左上角的功能表 
ALT+TAB         切換當前程式 
ALT+ESC        切換當前程式 
ALT+ENTER      將windows下執行的MSDOS視窗在視窗和全螢幕狀態間切換 
PRINT SCREEN      將當前螢幕以圖像方式拷貝到剪貼簿
ALT+PRINT SCREEN   將當前使用程式視窗以圖片方式拷貝到剪貼簿 
CTRL+F4         關閉當前應用程式中的當前文本(如word中) 
CTRL+F6         切換到當前應用程式中的下一個文本(加shift 可以跳到前一個視窗

2012年4月4日 星期三

用筆電當 AP 讓手機上網

在網路上找了一些方法,用 Window 7 內建的網路設定麻煩又不成功。

最後用了 Connectify,設定簡單又方便,

終於讓我的 Galaxy R 可以上網啦!!

2012年2月17日 星期五

2012年1月19日 星期四

[DEBUG] GraphEdit 9

我們可以用 GraphEdit 來看視訊或音訊檔案,預設是用什麼 Splitter, Decoder, Filter

和什麼 Renderer 來播放的。除此之外,我們也可以替換想要用的元件。

GraphEdit  可以在灌完 Microsoft SDK 後的路徑下找到。

Note: 如果在 Insert Filters 時,想要展開 DirectShow Filters,卻發生 crash,應該是和

其他 filters 相衝,可以把 K-Lite 移除在試試。

除了 GraphEdit,K-Lite 的 GraphStudio 也是相當好用,更勝於  GraphEdit,會自動列

出符合該檔案格式的 filters 以供選擇。

GraphEdit 的使用教學:
http://crazyktv.pixnet.net/blog/category/1933869

[DEBUG] ProcessMonitor 2.96

ProcessMonitor 可以幫助開發者查看特定應用程式正在執行時,所存取

的 RegKey 和檔案等等,是個相當方便的工具。

下面的網誌作者做了簡略的介紹:
http://blog.darkthread.net/blogs/darkthreadtw/archive/2007/08/18/977.aspx

2012年1月10日 星期二

[Win32] 自訂 Button 的顏色

在 Win32 的視窗程式設計下,想要自訂 Button 的顏色或 Button 文字的顏色,

並非易事,必須搭配 WM_DRAWITEM 來繪製自訂 Button。

1. 首先,在 Button 的 Properties Page 上將 Owner Draw 屬性設成 True。

2. 接收到 WM_DRAWITEM 訊息時繪製 Button 的樣式和欲顯示的字串。

    2.1 利用 DrawEdge() 可繪製 Button 被按下和沒按的樣子。

    2.2 DrawText() 可畫出文字,避免使用 SetWindowText(), 因為其會再觸發

          WM_DRAWITEM  很容易造成無窮回圈,而導致 Stack overflow。

FindWindow V.S. FindwindowEx

Findwindow() 是用來找 top-level (像是父視) 的視窗,而要找同層的視窗或子視窗時

,就必須用 FindwindowEx(),例如 : 當 Dialog_A 與 Dialog_B 有共同父視窗時,

FindWindowEx(GetParent(handle_A), NULL, NULL, L"Dialog_B");

即可取得 Dialog_B 的 handle。

2012年1月4日 星期三

[MS-DOS] 寫 BAT 檔的常用指令

1. 註解 :
    可在文字前加上 REM 或 :: 就代表該行為註解。

2. 變數 :
    利用 SET 可自訂變數的值,如 SET="hello"SET=1,需注意的是等號左邊不得
    有空白,SET =1 是錯誤的語法。
 
    其他用法  - 輸入 :
    如同 C 的 getchar(),利用 /p 也可讓使用者輸入參數。
    SET /p age=請輸入你的年紀:

    其他用法  - 取代指定的字串 :
  SET str=ababab
  SET str2=%str:a=b%   

  str2 == bbbbbb

  a 即為參照的字元
  b 為更改後的字元

    其他用法  -  取得指定位置的字串:
  SET str=0123456
  SET str2=%str:~1,3%   

  str2 == 12345

  1 即為從第幾位元開始
  3 為往後取3位   

3.  條件判斷 :
     如同 C 的 if-else,但在格式上有更多限制,若 if-else 同時出現則需伴隨著括號 "( )"
    ,如 : if condition ( statement ) else ( statement )
     但寫作下式會來的更好,
  
  if condition (
    statement
  ) else (
    statement
  )

     在這裡要注意 if  和 "(" 必須在同行 還有 ")" 和 "(" 必須和 else 在同行,否則都是錯
     誤的語法,寫成上式的好處是我們可以加上許多 statement,如下 :

  if condition (
    statement 1
    statement 2
    ...
    statement N
  ) else (
    statement 1
    statement 2
    ...
    statement N
  )

4. RENAME / REN :
    重新命名檔案或資料夾,EX: RENAME "%DST%\my.dll" "my2.dll"

5. DEL / ERASE :
    刪除檔案或資料夾,EX: DEL"%DST%\my.dll"


相關網站: http://www.computerhope.com/sethlp.htm