2016年3月17日 星期四

[win32] pyBarcode 在 cx_Freeze 之後,產生 barcode image 時出現 IOError: cannot open resource

稍微筆記一下這件事:

pyBarcode 使用 cx_Freeze 包裝成在沒有 python 環境下執行,
在產生圖檔的時候,出現IOError 的問題:

原因為 字型檔沒有在 cx_Freeze 包裝後的目錄中被找到:

[python installation directory]\Lib\site-packages\barcode\writer.py
 
PATH = os.path.dirname(os.path.abspath(__file__))
FONT = os.path.join(PATH, 'DejaVuSansMono.ttf')

然而 DejaVuSansMono.ttf 字型檔是附加在 pyBarcode 套件中,而路徑是使用絕對路徑,在經由 cx_Freeze 包裝後,自然就找不到。

MY Workaround:

使用 Windows 中的預設字型, 修改成:

#FONT = os.path.join(PATH, 'DejaVuSansMono.ttf')
FONT = 'arial.ttf'
 
這樣 Barcode image 上面的字型即為 Arial. 
或是,也可以自行將 DejaVuSansMono.ttf 裝至系統。
(這樣需要執行程式的電腦都要安裝該字型…不建議啦) 
  
 

2012年2月6日 星期一

Windows programming, standard input/output - AllocConsole()

前言
整理一下,在 windows programming 的時候,如何使用 printf, 這類的 standard I/O (標準I/O) 來顯示訊息幫助開發?

原因
在 windows programming,使用 MFC 的標準 windows template 都沒有 console window 來幫助顯示開發訊息,當然可以使用 IDE 中 debug message, 但這邊提供另一種方式,因為個人偏好使用 printf 快速地傾印資訊。

解法

先貼一段程式碼,從網路上抄來的…

  AllocConsole();

  HANDLE handle_out = GetStdHandle(STD_OUTPUT_HANDLE);
  int hCrtOut = _open_osfhandle(/*(long)*/(intptr_t) handle_out, _O_TEXT);
  FILE* hf_out = _fdopen(hCrtOut, "w");
  setvbuf(hf_out, NULL, _IONBF, 1);
  *stdout = *hf_out;

  HANDLE handle_in = GetStdHandle(STD_INPUT_HANDLE);
  hCrtIn = _open_osfhandle(/*(long)*/(intptr_t) handle_in, _O_TEXT);
  FILE* hf_in = _fdopen(hCrtIn, "r");
  setvbuf(hf_in, NULL, _IONBF, 128);
  *stdin = *hf_in;


然後再補上 streaming(串流) 的關係圖


這樣搭配看 應該很好理解程式碼。

補充說明
Process / Windows 就是目前在開發的 GUI 程式。

*stdout / *stdin 就是 CRT(C Run Time) lib 中的標準輸入跟輸出的指標,系統制訂的。

Console window 是使用 Window API, AllocConsole() 所產生。
搭配使用 GetStdHandle() 來取得 console standard I/O handle, handle_in / handle _out。

透過 _open_osfhandle() 將 console standard input/output handle 轉換為 file handle。
再使用 fdopen() 的方式,把 file handle, hCrtIn / hCrtOut 轉換為 file description。

最後,把 file description, hf_in / hf_out assigned to *stdin / *stdout 。
這樣視窗開發時,使用 printf 都不是問題囉!

有問題再留言囉!謝謝。

2011年4月16日 星期六

How to setup QuickSynergy as Client on Mac.

如何設定Mac上的QuickSynergy Client設定。


前言
 QuickSynergy 中所提供的 Mac 版本,在設定其為 Client 時,遇到了些不方便的地方。


原因
先來看看 QuickSynergy 的 Client 設定畫面。


在 Ubuntu 上面的 QuickSynergy, 正常有 Screen name 欄位.



在 Mac 上面的 QuickSynergy, 不太對呀…怎麼沒有 Screen name.
沒有了 Screen name 那怎麼在 Server side 定義呢?!原來是 QuickSynergy 會使用系統的 Local host name 當作 Screen name 連至 server side. 那我們該如何拿到自己的 host name呢?


其實很簡單,打開 Terminal 看一下提示字元前的名稱是什麼,再加上網域xxx (如:.xxx)。


【但小弟一開始沒發現這樣,於是就抓下了原始碼(From Google Project) 上面。自己動手加了顯示 Screen Name】




解法
加了一個元件來顯示目前Macbook中的 Host name.

(一切都只是為了方便於設定啦!)

下載:
執行檔(bin)
原始碼(source code)

後記:
如果想把Synergy 結合在系統的設定選項中,可以參考始用 SynergyKM
狀態能一下就看出來(在狀態列上),相當的方便。推廌始用。

2011年3月10日 星期四

Thinkpad X40 -- INTEL i855GM Driver 測試

Lucidi8xxFreezes


最近升級至 Ubuntu 10.10 之後,X40 的顯卡似乎就沒辦法正常運作圖行加速的功能。
於似乎找到了上面連結的討論。也花了一兩個早上在試著把圖顯加速的功能開啟。
試到至今的結果是可以開啟圖顯加速,但畫面會產生破損的情況。(等於沒用)
如果想要好一點的圖顯加速功能似乎也只能退回至10.04版加上舊版的kernel.
以上,很不甘心的結案。(會再持續觀察)

2011年2月7日 星期一

[Tips] 監控 dmesg 命令的即時訊息

  1. 參考來源watch-file-while-it-changes-dmesg.html
  2. 命令: watch "dmesg |tail --lines=$(($LINES-4))" 
  3. 參數說明:
    • watch: 關察 “命令” 的變化
    • tail --line: 欲顯視之行數多寡
    • $LINES:目前終端機之顯示行數

2010年12月28日 星期二

Ubuntu 10.10 & ThinkPad(X40) 中鍵捲動


事由
某日心血來潮在台年齡超過七年的ThinkPad上面裝上 Ubuntu 10.10,
結果…中鍵的功能卻少了可以上下捲動的功能,
只好靠著 GOOGLE 找到了這樣的文章~~來暫時解決一下囉!

參考網站文章
http://www.eastwoodzhao.com/thinkpad-middle-button-scroll-ubuntu-linux-10-04-lucid-lynx/

修改步驟

  1. 新增檔案
For 10.10
sudo gvim /usr/share/X11/xorg.conf.d/20-thinkpad.conf

For 10.04
sudo nano /usr/lib/X11/xorg.conf.d/20-thinkpad.conf

  1. 加入檔案內容
Section "InputClass"
Identifier "Trackpoint Wheel Emulation"
MatchProduct "TPPS/2 IBM TrackPoint|DualPoint Stick|Synaptics Inc. Composite TouchPad / TrackPoint"
MatchDevicePath "/dev/input/event*"
Option "EmulateWheel" "true"
Option "EmulateWheelButton" "2"
Option "Emulate3Buttons" "false"
Option "XAxisMapping" "6 7"
Option "YAxisMapping" "4 5"
EndSection

  1. 存檔及重新開機...

2010年11月30日 星期二

Porting lsusb & libusb on Android.

目的
在Android User Mode 下,透過 libusb 操作 USB Device,如:送出 Control MSG 至 Device。


參考文件
Using Android in Industrial Automation
Technical Report
A student semester project at the University of Applied Sciences Northwestern Switzerland for the Institute of Automation
Authors: Manuel Di Cerbo, and Andreas Rudolf
Project principal: Matthias Meier ⃝
FHNW/IA, 29.01.2010


 源碼下載
libusb-1.0.8.tar.bz2


檔案放置
libusb:  /external/libusb-1.0.8/
lsusb:  /external/lsusb/lsusb.c


編譯及安裝
  1. 新增 libusb-1.0.8/Android.mk
    ifeq ($(TARGET_ARCH),arm)

    LOCAL_PATH:= $(call my-dir)

    subdirs := $(addprefix $(LOCAL_PATH)/,$(addsuffix /Android.mk, \
    libusb \
    ))

    include $(subdirs)

    endif


  1. 新增 lsusb/Android.mk
    LOCAL_PATH := $(call my-dir)

    include $(CLEAR_VARS)
    LOCAL_SRC_FILES := lsusb.c
    LOCAL_MODULE := lsusb
    LOCAL_C_INCLUDES += external/libusb-1.0.8/
    LOCAL_SHARED_LIBRARIES := libc libusb
    include $(BUILD_EXECUTABLE)


  1. 修改libusb-1.0.8/libusb/io.c
    #ifndef TIMESPEC_TO_TIMEVAL
    #define TIMESPEC_TO_TIMEVAL(tv, ts)                                            \
           do {                                                                \
                   (tv)->tv_sec = (ts)->tv_sec;                                    \
                   (tv)->tv_usec = (ts)->tv_nsec / 1000;                        \
           } while(0)
    #endif /* end of TIMESPEC_TO_TIMEVAL */

    為了解決
    E: undefined reference to ‘TIMESPEC_TO_TIMEVAL’
    S: defined TIMESPEC_TO_TIMEVAL macro in libusb/io.c

  1. 在 memory map(/build/core/prelink-linux-arm.map 中加入 libusb.so(會依 platform 不同而有所不同)
    # extended system libraries
    libusb.so                0xAE600000
    libril.so                0xAE400000

    如果沒有定義 memory address,在編譯時會產生底下的錯誤訊息:
    E: build/tools/apriori/prelinkmap.c(137): library ’libusb.so’ not in prelink map
    S: build/core/prelink-linux-arm.map



  1. 在 init.rc 的 on boot 節(session) 中加入 mount usbfs 的命令:
    # usbfs
           mkdir /proc/bus/usb 0771
           mount usbfs none /proc/bus/usb -o devmode=0666

    重新make & download image 試試看在 shell 底下 lsusb 能不能動囉!

      2010年11月23日 星期二

      Missing USB Generic Mass storage driver on Windows XP

      今天在公司的電腦上面遇到了這個奇怪的問題,
      明明是該使用系統(windows XP) 預設的隨身碟驅動程式(USB storage driver),
      卻要求你要重新安裝驅動程式。

      經過一番調查原來是少了 

      C:\WINDOWS\inf\usbstor.inf
      C:\WINDOWS\inf\usbstor.PNF

      從別台電腦上補齊後,看似一切又正常了…
      以上供參考之。

      2010年8月26日 星期四

      H21 HSPA Modem 手動移除應用程式及驅動程式



      請先開啟終端機,路徑為應用程式/
      1.如果安裝 2.2.8.2 以後的版本,需刪除 H21PnP process
      sudo kill $(ps aux|grep 'H21PnP'|grep -v 'grep'|awk '{print $2}')

      2.刪除 H21 相關程式,開啟”應用程式”目錄,手動刪除底下這些項目(如果有存在)
      2.2.7.0 以前的版本
      QisdaH21Switch.app
      HSPA modem.app
      2.2.8.2 以後的版本
      HSPA Modem 目錄

      3.刪除驅動程式 AnchorUSB.kext QisdaSwitch.kext(如果已存在)
      sudo rm -R /System/Library/Extensions/AnchorUSB.kext/
      sudo rm -R /System/Library/Extensions/QisdaSwitch.kext/

      4.刪除驅動程式 QisdaVCP.kext
      sudo rm -R /System/Library/Extensions/QisdaVCP.kext/

      5.重新開機,再插上 H21 將會出現安裝的 HSPA Modem CDROM

      2010年6月8日 星期二

      Android Reference-RIL -- 初始化/訊息處理 簡略文字流程

      RIL 初始化流程:

      1. RILD 起動 RIL OBJ(ril.cpp) 中 RIL_StartLoop,其 New Thread 執行 RIL Event (ril_event.cpp) ::ril_event_loop() 為 for(;;) loop 等待處理 event list 中的訊息(event)
      2. RIL daemon(RILD) 載入 Libreferece-ril.so 
      3. RILD 透過 Dynaminc Loader(DL) dlsym() 取得 Librerfernce-ril.so 中的 RIL_Init function address(*rilInit).
      4. RILD 呼叫 (*rilInit) 取得 Reference-RIL callback function table[].
      callback function table[] --
      .RIL_VERSION,
      .onRequest(),
      .currentState(),
      .onSupport(),
      .onCancel(),
      .getVersion(),
      1. RILD 透過 RIL OBJ :: RIL_Register() 將 callback function table[] 儲存在 RIL OBJ. 並且取得 RIL socket-s_fdListen,等待連線。

      <<缺圖說明>>
      RIL 事件處理流程:
      1. RIL OBJ :: listenCallback 檢查是否有從 Phone process 的連線。
      2. 一旦確認為 Phone Process 連線,開取讀取 command,將其 Command Data 及 handle function (RIL :: processCommandsCallback) 設定至 RIL Event,並交至 Event Loop 處理。
      3. RIL Event :: ril_event_loop() 檢查是否有訊息待處理。會觸發 RIL Event :: firePending() ,其中會呼叫 Event Element 中的 handle function。[該步驟會重覆執行至所有訊息被處理結束。]
      4. 通 常 handle function 都被設定為 RIL :: processCommandsCallback(),結束 Stream data 後,即呼叫 RIL OBJ :: processCommandBuffer() 。
      5. RIL OBJ :: processCommandBuffer() 將依上層的 Request Number 利用 s_command[] table 轉換成相對應之 Request data 。
      6. 並且呼叫 s_command[] command 已定義的 dispatchFunction()。
      dispatchFunction() 大致分類為:void, string, strings, ints, smsWrite, Dail, SIM_IO, CallForward, Raw, CdmaSMS, CdmaSMSAck, GSMBrSmsCnf, CdmaBrSmsCnf, RilCdmaSMSWrite 這些類別。
      1. dispatchFunction 最終都會呼叫 Ref-RIL(Reference-RIL) callback function table[].onRequest() 並且代入 Request Number。
      2. Ref-RIL :: on Request() 會依 Requset Number 執行相對應之工作。

      2010年6月6日 星期日

      Android (or Android-x86) 開發環境的設置及工具安裝

      <<設定Build code 及環境的文章多不可數,但還是仍然放置在這邊,供自己查詢使用。 >>

      開發環境的設置及工具安裝:

      • 系 統設定 -- Using Ubuntu 10.04 or 9.10
      -- 安裝 JDK5
      # 開啟 APT 設定檔
      $sudo gedit /etc/apt/sources.list

      # 加入 server For sun-java5-jdk
      deb http://ir.archive.ubuntu.com/ubuntu jaunty-updates main multiverse

      # 更新及安裝 JDK5
      $sudo aptitude update
      $sudo aptitude install sun-java5-jdk

      -- 安裝 相關工具
      $sudo apt-get install gcc g++
      $sudo apt-get install flex bison gperf libsdl1.2-dev libesd0-dev libwxgtk2.6-dev build-essential zip curl libncurses5-dev zlib1g-dev valgrind libreadline5-dev

      -- 安裝 GIT
      $sudo apt-get install git-core

      -- 額外的部份: X11/Xatom.h & X11/Xlib.h (非必要):
      # provides Xatom.h
      $sudo apt-get install x11proto-core-dev 
      # provides Xlib.h
      $sudo apt-get install libx11-dev        
      • 建立 bin 目錄
      $mkdir ~/bin

      • 創 建 repo
      $curl http://android.git.kernel.org/repo > ~/bin/repo

              # 變更 repo 為可執行檔
      $chmod a+w ~/bin/repo

      • 把 repo 的路徑加至 $PATH
      # 編輯 ~/ 底下的 .bashrc 檔案,加上底下這行
      export PATH=$HOME/bin:$PATH

      • 建 立workspace
      # 新建目錄放置 Android Source Code. 底下使用 來代表自訂的名稱。
      $mkdir ~/
      $cd ~/
      • 從 官方 server 的 GIT source tree 下載 Source Code
      # 初始化要下載的文件清單
      $repo init -u git://android.git.kernel.org/platform/manifest.git

      # 同步資料庫(下載 Source Code)
      $repo sync
      • 在 有 HTTP Proxy 設定的情況下,我們需要透過 SSH , 把 git port 轉至 http port,所以需要透過 connect.c 程式,相關的設定如下:

      下載 connect.c, http://www.meadowy.org/~gotoh/ssh/connect.c


      請個別使用相關的設定值。
      請個別使用相關的設定值。 可使用 cd ~; pwd 查詢。


      編 譯 connect 執行檔,並且放置在 ~/bin/ 目錄下。
      $gcc connect.c -o connect
      $cp connect ~/bin/.
      $chmod a+x ~/bin/connect

      新增 proxy-cmd.sh, socks-gw.sh, sock-gw.sh 於 ~/bin/ 。
      $cd ~/bin
      $touch proxy-cmd.sh
      $chmod a+x proxy-cmd.sh
      $touch socks-gw.sh
      $chmod a+x socks-gw.sh
      $touch socks-ssh.sh
      $chmod a+x socks-gw.sh

      編輯 ~/bin/proxy-cmd.sh 內容:
      (echo "CONNECT $1:$2 HTTP/1.0"; echo; cat ) | socket | (read a; read a; cat )

      編輯 ~/bin/socks-gw.sh 內容:#!/bin/sh
      # ~/bin/socks-gw.sh
      # This script connects to a HTTP proxy using connect.c
      connect -H : $@

      編輯 ~/bin/socks-ssh.sh 內容:#!/bin/sh
      # ~/bin/socks-ssh.sh
      ssh -o ProxyCommand="/bin/socks-gw.sh %h %p" $@

      新增 proxy.sh 於 ~/ 。
      $cd ~
      $touch proxy.sh
      $chmod a+x proxy.sh

      編輯 proxy.sh 內容:
      #!/bin/sh
      # ~/proxy.sh

      # http proxy setting
      export HTTP_PROXY=http://:
      export http_proxy=$HTTP_PROXY

      # set git to use ssh over http proxy
      export GIT_SSH="/bin/socks-ssh.sh"
      export GIT_PROXY_COMMAND="/bin/socks-gw.sh"

      在 執行 repo sync 前,請先在workspace folder 中執行:
      $source ~/proxy.sh

      參考網頁:http://mmmyddd.freeshell.net/wiki/android/build.html#sec4

      2009年11月5日 星期四

      BOOTCAMP, EFI, MBR 一系列有趣的文章

      最近因為有人在討論 W32 如何完全安裝在Macbook上面,於是上網找到 Daniel Eran 幾篇文章在探討MAC與PC 間開機程序上面的不同之處。
      如果有興趣的先將就看一下原文吧!


      Imaging MacBooks: Understanding MBR, APM, & GPT
      http://www.roughlydrafted.com/RD/Home/0E960A5B-E16E-40A6-B4FD-E4C28F77A366.html

      How Boot Camp Works
      http://www.roughlydrafted.com/RD/Home/53E19DBD-BB3D-417C-A3C1-1F6172F5ECC8.html

      How Apple’s Firmware Leapfrogs BIOS PCs
      http://www.roughlydrafted.com/RD/Home/7CC25766-EF64-4D85-AD37-BCC39FBD2A4F.html

      An Introduction to Boot Camp
      http://www.roughlydrafted.com/RD/Home/E9EC61A2-E110-42C0-8C48-CD7D62197D32.html

      WIKI -- Extensible Firmware Interface
      http://en.wikipedia.org/wiki/Extensible_Firmware_Interface

      2009年10月19日 星期一

      如何替專案新增一個 Target/Product

      繼上篇 rename project 後,衍生出這個主題,如何在現有的專案中再新增一個 target 及 product.
      為了在專案開發中,不同客戶需要有不同的 Application Name, Version, Resource 等需求。
      不想再分出額外的 Code Base 又想符合客戶需求,我決定採用這方式來實作。

      或許,使用 compile option 是最常看到的方式。但小弟我實在太懶惰了,就用這種空間換取時間方式達成…
      1. 開啟 專案,在 Targets 的目錄中 Duplicate 原有的 target. (會產生 target-name copy 的項目)
      2. 在此 target-name copy 的項目上進入 Get Info 選單。
      3. 在 info window 中選取 "Build" page, 其中有個項目名稱為 Product Name,將它改成想要的名稱。
      4. 同時也修改 info.plist File 的名稱 (target-name copy).plist 置換為 (new-app name).plist
      5. 在 info window 中選取 "General page, 將 Name: 改成想要的名稱 (new-app name)。
      6. 回到 Xcode 主視窗中 尋找 (target-name copy).plist 將名稱改為 (new-app name).plist
      7. 開啟 (new-app name).plist

        
        
         CFBundleDevelopmentRegion
         English
         CFBundleExecutable
         new-app name
         CFBundleHelpBookFolder
         new-app name Help Folder
         CFBundleHelpBookName
         new-app name Help
         CFBundleIconFile
         
         CFBundleIdentifier
         com.my.Appkit.new-app.name
         CFBundleInfoDictionaryVersion
         6.0
         CFBundleName
         new-app name
         CFBundlePackageType
         APPL
         CFBundleSignature
         ????
         CFBundleVersion
         2.2.13.1
         NSMainNibFile
         MainMenu
         NSPrincipalClass
         NSApplication
        
        
        
        修改 CFBundleExecutable, CFBundleHelpBookFolder, CFBundleHelpBookName , CFBundleIdentifier, CFBundleName

      8. 複製一份 .plist 名字訂為 (new-app name).plist
      9. 複製一份 help folder 及 readme 名字訂為 new-app name Help Folder 及 new-app name Help
      這樣設定完後,在左上 Target 的選項中就會出現 "new-app name", 選擇它然後 Re-Build 我們就可以在build folder 中找到新的應用程式了。

      有發生任何奇怪的問題,歡迎來討論看看。
      謝謝。

      2009年7月15日 星期三

      如何替 XCode project(專案)改名

      出處:http://aplus.rs/cocoa/how-to-rename-project-in-xcode-3x/

      因為抓了 AnchorUSB sample 來改成自己要的 Driver, 之後想要換成另一個有義意的名字,
      上網找了這一篇,幫他做點中文化,讓不愛看英文的人,能快速地就知道怎麼變更專案名稱。
      底下都是些手動操作的步驟,

      1. 先做個備份的動作
      2. 進到欲修改的目錄,把 .pch 及 .xcodeproj (Xcode2 應該是只有後面這個)
      3. 刪除 build 目錄
      4. .xcodeproj 其實它是個封裝檔,進到封裝檔中,修改 .pbxproj (它是個XML檔案內容)
      5. 在.pbxproj 中把所有的舊名稱更換為新的名稱,並別忘了存檔。
      6. 修改 .plist 的檔名為新的名稱。
      7. 再使用Xcode 開啟專案,應該可以看到product 目前中紅色字樣的檔案。
      8. 試試 clean all/build是否可成功build出APP.
      • 目前,自己在換名稱的過程中,有必須再修改修改 .plist 檔案中 CFBundleExecutable 相對應的新名稱,之後才能順利執行應用程式。
      如果 有遇到 Rename 不順利的情況,再把錯誤訊息 貼上來。
      我們再來研究看看怎麼解決吧!Enjoy it~~

      2009年7月14日 星期二

      VIM search & replace tips 好用技巧(ctrl+r)

      文章出處:http://drakeguan.org/content/vim-%E7%9A%84-replace-by-search

      用了 VIM 也一段時間了,原來 search(搜尋) & replace(取代) 功能是這麼地方便使用。

      1. 使用 /<放上你的正則運算式> 此時應該可以在內文上反白已搜尋之目標。
      2. 打上 : 進入 command mode 輸入 s/" 然後按下 ctrl+r ,
      3. 按下 / 此時剛剛的搜尋(正則運算式)就自動地被貼上來。
      4. 再來就是取代字串囉!
      • %s/<>/<>/gc 可以搜尋整隻檔案,並在取代的過程會提示你是否要取代。
      大家一起來用 VIM 吧!

      多補充個搜尋的小技巧吧!怎麼樣弄出像UltraEdit 一樣的搜尋結果清單呢?
      很簡單 ~~

      %g/<pattern>/z#=<num>

      <pattern> 為搜尋的字串。
      <num> 為該行上下個<num>的顯示。

      2009年7月1日 星期三

      使用 Cocoa 建構 Hello World!!

      在此分享如何使用 Xcode3 建構一個Cocoa Application.
      例子當然是世界名著 Hello world. 如果底下說明有不正確的地方,還請麻煩告知。

      當然 XCode3 要先裝好…然後打開它點選一下New Project吧!

      1. 我們這次要建構一個Cocoa Application,如下圖,

      選取之後我們就命名它為Hello World, 及我們所要擺放資料夾的位置。
      (這個步驟就自行發揮)

      2. 接著我們可以見到XCode 的主畫面如下,
      紅色字體的部份就是我們以後的Hello World application.
      如果有成功的build project 就可以見到它會轉變為黑色的字體。


      3. 我們先必需在這個Application中新增一個自己的Subclass,
      在Class 資料夾上面按右鍵,選取Add -> New File.


      4. XCode 會要求我們選擇所需要的種類的檔案,我們這次選取 Objective-C Class
      因為小弟一直都習慣使用C, Objective-C 對我而言是個比較快可以入門的方式。

      5. 接著我們必需命名我們的檔名,通常檔名即我們Class 的名字,
      在這邊我們給它為"appCntrl", 即為 Application Controller


      6. XCode 的部份先告一段落,我們從XCode 中選取 MainMenu.xib(或 MainMenu.nib)
      其實是指同樣的東西,以後有機會再來討論中間的差異。
      雙擊 xib 後,會帶出Interface Builder,這是決定 Application Layout的工具,
      其中可以看到如下圖的視窗,然後我們必需從Library 中拉NSObject至這個window中,
      它會生成一個"Object"的圖示。


      6. 再來要對這個"Object"做些設定的動作,先選取 "Object"圖示,然後到Inspector window中,
      點選 i 這頁後,在上方Class 的部份,我們打入我們的"appCntrl"。
      (如果找不到,可以試著做看看從File底下Read Class files的動作後,再來找看看)


      6. 接著這個部份就自行發揮,在Window 上面加上Label & Button,如下圖,


      7. 有了可收事件 跟顯示資訊的元件後,我們回到inspector, 先點我們新加的Objec, 再至 i 這個頁面,
      我們在Outlet & Action 這兩個部份各加入ID,名稱的部份是可以變更的。(這部份我並沒有修改)
      在最底下Name 的欄位填入"appCntrl" 這樣可以識別至XCode中的appCntrl Class.
      做完上面的設定後,至File 底下執行 Write class file 的動作,
      它可能會問是是要replace 還是merge 這個就見人見智了。

      /// 小說明一下,這個動作會將剛新增的 Oulet/Action 加到 appCntrl.h & .m 檔案中。
      /// 你可以換成在Xcode 中自己手動新增,然後在Interface Builder 中從read class file的動作中讀進來。

      8. 在Window 上面我們配置了 Label & Button 兩個元件後,
      我們必需把它們跟自己新增 appCntrl Class 中的 Outlet 及 Action 做個連接。

      /// 如果你把Outlet 想像成 output, Action 想像成 input,就可以理解成,
      /// 我們會從 Button 收下mouse click 的事件,然後傳到 appCntrl Object,
      /// 經過我們的處理後,再把資訊呈現至 Outlet 上面。
      /// (使用 appCntrl Object的原因,是Object 為實體,Class 只是個宣告類別)

      /// 那連接的動作如何完成,如果是A要丟東西給B ,就選取A 按下Control 鍵拉至B 上面。
      /// 如下面的動作,選取 Button 按下 Control 拉至 appCntrl ,
      /// IB(interface builder)會跳出視窗要求選取處理事件的 "Method" (也可看成Funtion啦)
      /// 當然我們就選取自己新增的 myAction1 來處理這個事件。

      同樣的方式 我們拉appCntrl 至Label 上面,把它指定為 myOutlet1.

      9. 在inspector window 上面 我們可以看到完成的結果。


      10. 在IB 存檔完,它的工作就先告一段落了,接下來要自己動手打點程式了。
      (終於有程式了...)

      先來看看appCntrl.h 的內容,
      #import <Cocoa/Cocoa.h>
      @interface appCntl : NSObject {
          IBOutlet id myOutlet1;
      }
      - (IBAction)myAction1:(id)sender;
      @end
      
      /// 這個部份,就是剛我們在IB做完那些動作,按下 Write class file就會幫我們加進來的。
      /// 如果一開始在這邊自己動手加程式,也可以反過來在 IB 用 read class file 放進 IB.
      /// 小弟比較懶惰~~所以我選擇打字比較少的動作。

      /// 不是說要打些程式碼嗎?怎麼上面不需要…嘿嘿…
      /// 接下來在 appCntrl.m 中我們就就要輸入底下這些東西…
      找到myAction1: (id)sender { } 這個段落中,加入你所沒有那段程式。
      #import "appCntl.h"
      @implementation appCntl
      - (IBAction)myAction1:(id)sender {
          static Boolean shownHello = FALSE;
          
          if (FALSE == shownHello) {
              [myOutlet1 setStringValue:@"Hello world!"];
              shownHello = TRUE;
          }
          else {
              [myOutlet1 setStringValue:@""];
              shownHello = FALSE;
          }
      }
      @end
      
      /// 這邊先不解釋這些 有點像C 又不太像C 的 Objective-C 的語法。
      /// 小弟只想先快速地建構起一個hello world 示範程式。

      打完程式後,我們按下 Build & Go 就等著程式跳出來囉!
      (如果沒有Compiler error 的話,真的不幸跑出來的話,再把msg 貼上來,再來看看怎麼解)

      首先是這樣的畫面,


      然後按下Button 後,"Hello World!!"就會顯示
      再接著按一下Button ,Hello World 就消失不見,一直重覆做出現不見的事情。
      (有點小白痴,但它可以動了。:D)
      希望 這篇有幫到你了解整個建構Application 的流程,
      當然中間 Objective-C的那段程式碼沒有解釋,先留待下回小弟充板面的內容吧!

      /*
      ** 另外,appCntrl & appCntl 是都指一樣的東西,因為小第太懶的再重新抓一次圖
      ** 但又覺得名字應該用 appCntrl 比較適合,所以在做的時候,記得用一樣的名稱。
      */


      最後,上面步驟,或是說明有不正確的地方,還請教導一下。因為我也是新手啦!
      哈哈哈~~!! 祝大家玩的愉快。

      2008年12月9日 星期二

      開啟Acer AspireOne Xfce 選單(不使用command line)

      1. 開啟桌面選單功能:執行/usr/bin/xfce-setting-show程式。
      2. 點選”桌面”->”行為”,將”按下右鍵顯示桌面清單”勾選。

      2008年3月3日 星期一

      2008年3月2日 星期日