2019年4月16日 星期二

Delphi TList 在 iOS 的坑!?

開發環境:Delphi XE10 Seattle Version 23.0.20618.2753
執行環境:Win10x64, iOS 12.2

以下的程式碼,Win32 版可以正常執行 Button1Click 但在 iOS 則會出現
Run-time Error : Access violation at address xxxx

type
  TMyObj = class(TObject)
  public
    Name, Value: string;
  end;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
    MyList: TList;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

procedure TForm1.Button1Click(Sender: TObject);
var
  temp: TMyObj;
begin
  temp := MyList.Items[3];
  Memo1.Lines.Add(temp.Name);
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  myObj: TMyObj;
  i: Integer;
begin
  MyList := TList.Create();

  for i := 0 to 10 do
  begin
    myObj := TMyObj.Create();
    myObj.Name := 'Name'+i.ToString;
    myObj.Value := 'Value'+i.ToString;
    MyList.Add(myObj);
  end;
end;

發現要改用 TListT<MyObj> 或 TObjectList<MyObj> 在 iOS 才會正常


uses Generics.Collections;
var
  MyList: TObjectList<TMyObj>;

MyList := TObjectList<TMyObj>.Create();

2018年12月22日 星期六

如何在 Blogger 顯示程式碼


● 設定方式參考:
[探索 3 分鐘] 用 JavaScript 與 css 客製化部落格 blogger
使用Google Code Prettify漂亮顯示讓程式碼自動分辨顏色
在 Google Blogger 顯示程式碼

● 選用樣式:
https://rawgit.com/google/code-prettify/master/styles/index.html
https://jmblog.github.io/color-themes-for-google-code-prettify/

例如:選用 Sunburst 的樣式,把 sunburst.css 裡面的碼,貼到 「HTML / JavaScript 」小工具的 style 區塊中

● 設定 Delphi 語言顯示:
在文章的 code 區塊中,設定 class="pascal"

● 程式碼中有 html 語法標籤的時候要轉碼
http://demo.smarttutorials.net/html-xml-adsense-parser/

<pre class="prettyprint">
<code class="pascal">
</code>
</pre>

Delphi XE10.3 Rio 實作 Android 8 的 Notification Channels

 
{$IFDEF ANDROID}

uses FMX.PushNotification.Android, Androidapi.Helpers, Androidapi.Jni.Os,
  Androidapi.Jni.App, Androidapi.Jni.GraphicsContentViewText,
  Androidapi.Jni.JavaTypes, Androidapi.JNIBridge;
{$ENDIF}

procedure TForm1.createNotificationChannel();
var
  LService: JObject;
  FNotificationManager : JNotificationManager;
  FNotificationChannel: JNotificationChannel;
  LApplicationInfo: JApplicationInfo;
  targetSdkVersion: Integer;
begin
{$IFDEF ANDROID}
  LService := TAndroidHelper.Context.getSystemService(TJContext.JavaClass.NOTIFICATION_SERVICE);
  FNotificationManager  := TJNotificationManager.Wrap((LService as ILocalObject).GetObjectID);

//    if TAndroidHelperEx.CheckBuildAndTarget(TAndroidHelperEx.OREO) then
// Tony 參考 https://github.com/DelphiWorlds/KastriFree/blob/master/Core/DW.Android.Helpers.pas 改寫
  LApplicationInfo := TAndroidHelper.Context.getPackageManager.
    getApplicationInfo(TAndroidHelper.Context.getPackageName, 0);
  targetSdkVersion := LApplicationInfo.targetSdkVersion;

  if (TJBuild_VERSION.JavaClass.SDK_INT >= 26) and (targetSdkVersion >= 26) then
  begin
    FNotificationChannel := TJNotificationChannel.JavaClass.init(TAndroidHelper.Context.getPackageName, StrToJCharSequence('default'), 4);
    FNotificationChannel.enableLights(True);
    FNotificationChannel.enableVibration(True);
    FNotificationChannel.setLightColor(TJColor.JavaClass.GREEN);
    FNotificationChannel.setLockscreenVisibility(TJNotification.JavaClass.VISIBILITY_PRIVATE);
    FNotificationManager.createNotificationChannel(FNotificationChannel);
  end;
{$ENDIF}
end;

2018年3月14日 星期三

聖經 App 分享


除了我們常看的「新標點和合本」聖經之外
(CUNP - Chinese Union Version with New Punctuation) ,還有許多其它的翻譯版本 (推薦如下)

中文:
新譯本 (CNV)、
新普及譯本 (CNLT - Chinese New Living Translation)

英文:
The Message (MSG)、
New Living Translation (NLT)、
New International Version (NIV)

註:King James Version (KJV) 是古英文的版本

[ 聖經 (YouVersion.com) - Life.Church ]
 Android APP / iOS APP

<特色>
● 需要 Google 或 e-mail 註冊 / 登入
● 無廣告 (可捐款支持他們!)
● 介面簡潔、功能多
● 語音聖經:CUNP, CNV, NLT, MSG…等
● 離線版聖經(可下載):
   新標點和合版 (神 / 上帝)、MSG、NIV…等
● 線上版聖經(需連上網路):
   新譯本、NLT…等




[ 漢語聖經 Chinese Bible - 漢語聖經協會 ]
Android APP / iOS APP


<特色>
● 無廣告
● 二種版本對照功能
● 字典
● 免費版本:和合本、七十士譯本 (Septuagint LXX)…等
● 付費版本:新普及譯本 (CNLT)
   價格:Android NT$320, iOS NT$300

Tony 註:2018/03/15 目前找到唯一提供此版本的 App






[ 中文聖經 圣经  - ps23 ]
只限 Android APP (作者網址 http://iesus-bible.blogspot.com)

<特色>
● 無廣告
● 區分舊約、新約、章:可以快速找到經文所在
● 功能精簡、可調字體大小、書籤、醒目
● 夜間模式 (黑底白字)

Tony註 : 搜尋功能有時候會異常(找不到東西)





[ 漢語聖經網頁版 ]
http://www.chinesebible.org.hk/onlinebible/index.php




2016年7月6日 星期三

番茄土豆 - 這不是一道菜


個人時間管理 -- 一次專注做好一件事情

番茄土豆 ]
就是番茄鐘(Pomodoro) + 土豆 (To-Do-List) 組成的 GTD  (Getting Things Done ) 時間理理利器
參考:番茄土豆: 番茄鐘 + GTD 夢寐以求的時間管理利器


10個幫你提升工作效率的好用手機App、Chrome套件

Keep Focused 保持25分鐘專注力的 Pomodoro 工作法小工具

PC Mac 桌面上最好的番茄鐘軟體,中文免費版下載

Focus Booster 善用桌面電子番茄鐘,讓工作專注力加速

[ 番茄 ]

POMODORO TECHNIQUE --- DO MORE AND HAVE FUN WITH TIME MANAGEMENT

Keep Focused - an enhanced tool for Time Management using Pomodoro Technique

番茄鐘工作法: 25 分鐘改變效率的 10 個番茄鐘工具

[ Android ] -- 發條番茄鐘、 番茄土豆

[ 同場加映 ] -- Time Meter Time Tracker


2016年6月22日 星期三

BCB6 TServerSocket 元件注意事項

常會發生 Asynchronou Socket Error #1000xxx

解決方式如下:
 一、將相關的程式碼用 try catch 包起來,以免出現 Exception 程式就卡住
二、將 ErrorCode 清掉,並關閉 Socket

void __fastcall TForm1::ServerSocket1ClientError(TObject *Sender, TCustomWinSocket *Socket,
TErrorEvent ErrorEvent, int &ErrorCode)
{
 //分析錯誤
 ErrorCode=0;
 Socket->Close();
}

2016年5月24日 星期二

Context - Android

參考:Context都沒弄明白,還怎麼做Android開發?


/**
 * Interface to global information about an application environment.  This is
 * an abstract class whose implementation is provided by
 * the Android system.  It
 * allows access to application-specific resources and classes, as well as
 * up-calls for application-level operations such as launching activities,
 * broadcasting and receiving intents, etc.
 */
public abstract class Context {
    /**
     * File creation mode: the default mode, where the created file can only
     * be accessed by the calling application (or all applications sharing the
     * same user ID).
     * @see #MODE_WORLD_READABLE
     * @see #MODE_WORLD_WRITEABLE
     */


凡是跟UI相關的,都應該使用Activity做為Context來處理

2016年5月20日 星期五

Chrome run Android app ! ?


參考:免模擬器!直接用 Chrome 在電腦跑 Android App!

[ 環境預備 ]
1. 下載 ARChon Custom Runtime
2. 在 Android 安裝 ARChon Packager (Google Play) 或 bpear96/ARChon-Packager
3. 在 Android 執行 ARChon Package ,選擇目標 app ,作出來的檔案會在  /sdcard/ChromeAPKS 的目錄中,AppName.zip

[ 安裝方式 ]
1. 解壓縮 ARChon Custom Runtime ,會是像 vladikoff-archon-6ad1d59d5f1a 的資料夾

2. 在Chrome的網址列輸入 chrome://extensions
勾選「開發人員模式」,並選擇「載入未封裝的擴充功能」,然後將路徑指到步驟1的資料夾


3. 將 AppName.zip 解壓縮,一樣選擇「載入未封裝的擴充功能」,然後將路徑指到 AppName 解完壓縮的資料夾 (有 _locales, vendor 資料夾的上一層)

4. 在Chrome的網址列輸入chrome://apps,就可以看到App圖示。

5. 不一定可以執行
註:FMX 作的 PSC.app 就不能執行

[ twerk ] 將 Android APP (APK 檔案) 包裝成 Chrome 瀏覽器外掛

2016年5月17日 星期二

HTML 常用備忘


[電腦] 特殊字元 HTML 編碼對照表

因為這些是特殊符號,在 html 裡面,要用下列方式代替

  • And 符號 ' & ' (ampersand) becomes '&amp;'
  • 雙引號 ' " ' (double quote) becomes '&quot;'
  • 單引號' ' ' (apostrophe/single quote) becomes '&apos;'
  • 小於符號' < ' (less than) becomes '&lt;'
  • 大於符號' > ' (greater than) becomes '&gt;'
  • 空白符號 ' ' (no-break space) becomes '&nbsp;'
常用標籤:
<p>分段
<br /> break 換行 

2016年5月16日 星期一

Blogger 如何設定 Syntaxhighlighter 讓程式碼更容易讀

「我的網誌」管理頁面 > 範本 > 編輯 HTML
在 </head> 的上面,加入這個部分的程式碼,然後按儲存範本

<!-- BEGIN SyntaxHighlighter BEGIN -->
<link href='http://alexgorbatchev.com/pub/sh/current/styles/shCore.css' rel='stylesheet' type='text/css'/>
<link href='http://alexgorbatchev.com/pub/sh/current/styles/shThemeDefault.css' rel='stylesheet' type='text/css'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shCore.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushAppleScript.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushAS3.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushBash.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushColdFusion.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCpp.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCSharp.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCss.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushDelphi.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushDiff.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushErlang.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushGroovy.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJava.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJavaFX.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJScript.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPerl.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPhp.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPlain.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPowerShell.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPython.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushRuby.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushSass.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushScala.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushSql.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushVb.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushXml.js' type='text/javascript'/>
<script language='javascript' type='text/javascript'>
 SyntaxHighlighter.config.bloggerMode = true;
 SyntaxHighlighter.defaults['auto-links'] = false;
 SyntaxHighlighter.defaults['toolbar'] = false;
 SyntaxHighlighter.all();
</script>
<style type="text/css">
  .syntaxhighlighter { 
     overflow-y: hidden !important; 
     overflow-x: auto !important; 
  }
</style>
<!-- END SyntaxHighlighter END -->


使用方式,在編輯 html 時,加入
<pre class="brush:cpp;" name="code">
程式碼...
</pre>
cpp 可改成對應的語言
我第一次設定時,程式碼排版異常,最後是把範本砍掉重練,然後照上述方式再次設定,才 OK

使用注意事項:https://github.com/syntaxhighlighter/syntaxhighlighter/wiki/Usage
轉換 html 網站:http://accessify.com/tools-and-wizards/developer-tools/quick-escape/default.php

2015年2月3日 星期二

Android 練曲 APP

[ Audipo ] 免費版:有廣告
Audipo 畫面

推薦特色:多段標記、降速抓歌的好幫手。

可用三分之二的畫面顯示 track bar ( bar height 可調),來做「多段」標記 (還可以為段落命名),一般的 app 只有單段標記 (A-B loop),而且因為 track bar 的總長度變長了,除了標記不會都擠在一起之外,更容易跳到我們想標記的位置。

Speed 調整範圍 :x0.25 ~ x 4.00 倍速

Pitch 調整範圍: -12 ~ +12 semi-tones (半音)
註:付費升級專業版,才有此功能,但可先試用一個星期。
iOS 版也有此 app ,但沒有調 pitch 的功能 Orz







使用方式:
1. 標記段落 (e.g. 前奏 / 間奏 / 尾奏 / 橋段) -  按下三角形播放按鈕後,在段落開頭的前一小節 (為了練習時有個緩衝時間可以預備,e.g. 鼓的 sign in),按下「▼+」的按鈕,就會在該位置產生一個標記 (小的黃色三角形和圓點)。

2. 此時音樂繼續播放,到這個段落結束的時候,再按下「▼+」的按鈕,就會產生另一個標記。

3. 先按暫停後,按下「▼←」、「▼→」就可以直接跳到「上一個 / 下一個 標記」

4. 按下  ,進入「Mark Repeat On」模式,再按「播放」就會一直在這二個標記中一直重覆播放,然後就可以試著把節奏、弦律、和弦…等抓出來,或者跟著練習。


5. 若覺得快歌速度太快,抓不到拍子或跟不上,就可以減速。如果已經練熟了,可以試著加速 (x1.2)「自我操練」一下。


升級專業版 :NT$132 (請支持程式開發者的辛勞 XD)
強化的部分特色:
‧ Equalizer / Bass Booster / Reverb 強化某頻段的聲音,例如:抓 bass line
‧ Export audio tracks to wav/mp3 file 將調過 speed / pitch 的曲子匯出成檔案
‧ Remove ads (讓您不再覺得廣告礙眼)
‧ Pitch shift control (升降 key 的好幫手 )
‧ Vocal remover (人聲混在左右聲音的檔案才有明顯的效果)
‧ Mark data import (某人已經標記好的結果可以直接拿來用 XD )
其它:Widgets, Shuffle Play, Sleep timer, ....



Music Speed Changer ] 免費版 (主畫面有廣告 )
推薦特色:
1. 介面簡單易用
2. 可將調整過 speed 和 pitch 的結果,另外存成一個 aac 檔

Speed 調整範圍 :33% to 300%
Pitch 調整範圍: -12.0 ~ +12.0 semi-tones (半音)
支援格式:mp3, wav, flac, aac/m4a





[ Maple Player Classic ] 免費版
推薦特色:
1. 免費版就可以調 EQ, Spped, Pitch,但只有 A-B 段 loop
2. 而且廣告只出現在設定頁面,不會干擾主畫面的操作。

支援音樂檔案格式 : mp3, ogg, wav (8/16bit pcm)
Speed 調整範圍:x0.25 ~ x4.0
Pitch 調整範圍:-6.00 to +6.00 semi-tones (半音)



2011年10月29日 星期六

const 的範例

//int Proc1(int* array, int len) // 放入a2就會有error
int Proc1(const int* array, int len) // a1, a2 通吃
{
  int sum=0;
  //array[0] = 0; // 錯誤,因 array 是 point to const int,所以不能改值
  for(int i=0; i>len; i++)
    sum += *(array+i);
  return sum;
}

void test(void)
{
  //const int SIZE; // 錯誤, const 變數要給值初始化 (之後就不能改了)
  const int SIZE = 5;
  int const size = 5;  // 效果同上,宣告的方式強調它是 int 的 const
  int a1[SIZE] = { 3, 2, 5 };
  a1[3] = 8; a1[4] = 9; //可宣告後給值
  const int a2[SIZE] = { 1, 3, 5, 7,  9 }; //只能在宣告時初始化給值
  int sum1 = Proc1(a1, SIZE);
  int sum2 = Proc1(a2, SIZE);
  Memo1->Lines->;Add ("sum1=" + String(sum1));
  Memo1->Lines->;Add("sum2=" + String(sum2));
  int *p1;
  p1 = a1 +2;
  *(p1-1) = 4;
  //p1 = a2; // 錯誤,point to 非const 不能指向 const物件
//------ pointer to const ------------------
  const int *p2;
  p2 = a1 + 1;
  //*p2 = 3;    // 錯誤,不能透過 point to const 來改值
  p2 = a2 + 3;  // OK ,可以指向 const物件
  //*p2 = 3;    // 錯誤,不能透過 point to const 來改值
  int const *p3;  // 等同 p2,但此方式宣告較不清楚
  p3 = a1 + 1;
  //*p2 = 3;      // 錯誤
  p3 = a2 + 3;
  //*p2 = 3;      // 錯誤
//------ const pointer ------------------
  //int * const p4; // 錯誤,const 指標值初始化就要給值了
  int * const p4 = a1 + 1;
  *p4 = 3;  // OK,可以改值
  //p4 = a1 + 3;  // 錯誤,初始化後就不能指向它處
  //int * const p5 = a2; // 錯誤,不能指向const int物件
  //const * int p6; //錯誤的宣告方式
//------ const pointer to const ------------------
  const int * const p7 = a1; // 指向 const int 的 const指標,但沒啥屁用
  //*p7 = 2; // 不能改值
  //*p7 = a1 + 2; // 也不能指到別的地方
}

2010年9月21日 星期二

Ubuntu系統相關

1. 新增文件於Linux系統下,「屬性」可以勾選與取消「允許檔案作為程式執行」,但若檔案存於NTFS,則無法取消勾選。(所以開文字檔,也會跑出視窗問你要執行還是要顯示內容)

2. RAR檔
sudo apt-get install rar


啥?裝不起來?


系統 => 管理 => Synaptic 套件安裝程式
Synaptic 套件安裝程式:設定 => 套件庫



將第3個選項, "Software restricted by copyright or legal issue (multi verse)" 打勾。


3. 7z檔
sudo apt-get install p7zip p7zip-full



2009年7月25日 星期六

Hello DLL - 2初嚐Win32DLL

專案名稱:VCDll
目的:
一、將自己以前作的Win32 Static Link Libary,變成Win32 Dynamic-Link Library(DLL)
二、示範將一些標準函式庫輸出
(也可以解決OpenCV在BCB6下的問題 >"< => 找不到cvhaartraining.dll的run-time error)

方法:

1.用精靈新增一Win32 Dynamic-Link Library專案
選擇「A DLL that exports some symbols」 (因為會自動產生所需檔案 :p )

2.將 VCLib.h 和 VCLib.lib (於build VCLib專案後產生)
複製到VCDLL專案的目錄下,並加入專案中(使用方案總管)

3.在stdafx.h中 #include "VCLib.h" 及一些標準函式庫

4.常見的.h寫法
(VCDLL是這個例子的專案名稱,其它的開發環境或專案可用能的是 WIN32_API)

#ifdef VCDLL_EXPORTS
#define VCDLL_API __declspec(dllexport) //export dll時用
#else
#define VCDLL_API __declspec(dllimport) //import dll時用
#endif

a.當include這個.h檔,要export dll時
編譯器會自動加上相關的編譯參數而#define VCDLL_EXPORTS
(VC "專案屬性 =>C/C++ =>前置處理器" 中的設定 或 BCB的-WD編譯參數)
以使用 __declspec(dllexport)

b.當include這個.h檔,要import dll時
因為沒有#define VCDLL_EXPORTS,故使用 __declspec(dllimport)

6. 將欲export的函式宣告放在 extern "C" { ... }
Q:啥米係 extern "C" ? (自問自答中…)
A:編譯時將函式自動更改成不同名(依compiler而不同),稱為『name mangling
在函式的宣告前加上extern "C"這個修飾詞,
強制將函式名稱以C語言的形態重現,而非以C++語言的形態出現

如此一來就可以防止name mangling造成 :
在其它compiler要import同一個dll時會出問題 (例如VC下的dll/lib 要給 BCB用 =__=")


但是要注意,多載函式不能加上extern "C"這個修飾詞
(不然的話,有好幾個函式都同名,要link哪一個?
overloading function在compile-time就是用 name mangling 的方法實作,以便link時不會出錯)

7.在VCDll.cpp中加入程式碼,為了展示dll的實作
只將函式名稱更改或變大寫後,然後呼叫原函式
(將好幾顆水餃包成一個大包子,好吃嗎?)


註:除了上述步驟,其它的參考程式碼皆為VC的專案精靈產生
VC展示了:匯出 "變數"、"函式"、"類別建構式" 的範例程式碼
而在//---Tony----註解後的部分是自行加入的程式碼

ps2. 很久以前就想買了,但那時的大學生活太精彩了,沒錢也沒閒(一不小心就透露年紀了)
ps3. 雖然也出了好一陣子,但對一個上班族來說還是有點貴,有小錢但更沒閒
ps4. 退休時再來玩吧…
嗯…離題了

8. Build專案後可以得到VCDll.lib及VCDll.dll (怎麼用?下回再分解…)
一般在VS開發程式的習慣是:改好程式碼後就按[綠色小三角] (開始偵錯(F5))
此時VS會Build,當沒有error時執行build好的「執行檔」(.exe)

可是這個專案的「成品」不是.exe,而是 .dll及 .lib,
所以VS會跳一個視窗出來叫你選一個「偵錯工作階段時」的可執行檔

為了避免麻煩還要取消視窗,請忍住不要去點[播放]鍵,而直接按[F7]來建置(Build)方案
不然「哇辛卡北媚,跪閃關…」的歌聲可能真的會從喇叭傳出來…

Hello DLL - 1與函式庫的第一次

開發環境:
VS 2008 Standard 繁中 SP1 (9.0.30729.1 SP)
XP pro sp3

方案內容:
實作自行開發的Static Link Libary靜態連結函式庫專案,
以及使用此函式庫的另一個Win32主控台專案

1.VCLib專案定義函式原型(.h)並實作(.lib),以供其它程式使用
(Compile時用到.h Link時用到.lib)

2.TestStaticLib專案使用VCLib專案中的函式,如同使用標準函式庫一樣
而其中的差異是:標準函式庫的路徑,IDE(開發環境)已經預設好了(在安裝時)
但使用自行開發的函式庫.h及.lib時,檔案的路徑需在專案屬性中手動加入

使用標準函式庫
#include
....
void main(void)
{.... printf("");}

<對照>
使用自己的函式庫
#include
...
void main(void)
{.... VCLib_MyFunction();}
//--------------------------------------------------------------------------------
實際操作:

一、使用VC的專案精靈,產生VCLib專案

新增Win32專案=>選Static Static Library,不勾「Pre-Compiled header」及「MFC support」
得到一空的專案,自行編寫及加入.cpp及.h

專案名稱:VCLib
主要原始檔:VCLib.cpp, VCLib.h
主要函式:int AddMethod(int a, int b)
用途:將二個整數相加的值回傳


二、在方案中新增一新專案TestStaticLib
類型:主控台應用程式,可勾選「先行編譯標頭檔」
(以後需要include的函式庫都加在stdafx.h中即可)

專案名稱:TestStaticLib
主要原始檔:TestStaticLib.cpp
目的:#include "VCLib.h"的int AddMethod(int a, int b)來用

//--------------------------------------------------------------------------------
Tony :錯誤訊息及改進方法

fatal error C1083: 無法開啟包含檔案: 'VCLib.h': No such file or directory

若複製一份VCLib.h檔至TestStaticLib專案目錄下,然後用#include "VCLib.h"簡單可行
(只在方案總管內加入.h檔,在Compile或Build時無效的,因為Compiler
仍不知道.h的路徑,方案總管對標頭檔的增減只算是VS IDE的一個檔案管理工具罷了)

但要更改VCLib.h時,要手動做一次上述動作,既麻煩又常會忘。
故改用 #include
然後在[專案屬性]設定好路徑
C/C++ => 一般 => 其它include目錄
加入 "$(SolutionDir)VCLib\" 這個巨集的相對路徑
以後就只維護一份VCLib.h即可
--------------------------------------------------------------------------------
TestStaticLib.obj : error LNK2019: 無法解析的外部符號
"int __cdecl AddMethod(int,int)" (?AddMethod@@YAHHH@Z) 在函式 _wmain 中被參考

TestStaticLib =>專案屬性=>連結器=>其它相依性=>加入VCLib.lib
(雖然已經加入路徑了,但VC卻不知要用它 =__=)
-------------------------------------------------------------------------------
LINK : fatal error LNK1104: 無法開啟檔案 'VCLib.lib'

TestStaticLib =>專案屬性=>連結器=>將VCLib.lib的路徑加入
此方案中因為VCLib專案的輸出檔預設為$(OutDir)\$(ProjectName).lib
故路徑亦可用$(OutDir)
--------------------------------------------------------------------------------

Visual Studio方案相關:

因為VCLib專案要先產生VCLib.lib,才能供TestStaticLib用
故方案屬性=>專案相依性=> 專案TestStaticLib要勾選"相依於VCLib"
如此在"建置方案"時,就會有對的順序,不致有錯誤訊息產生
--------------------------------------------------------------------------------
設定路徑小技巧:
在選擇如Include路徑的對話方塊,右下角有個[巨集]按鈕,可提供
一些相對路徑的巨集名稱,例如:$(OutDir)
使用相對路徑時,就算將整個方案的資料夾搬到別的路徑或電腦下
仍然可以正常Build (但安裝SDK時的相對路徑也不可被手動更改)

程式碼範例還在找地方上傳…