顯示具有 BCB 標籤的文章。 顯示所有文章
顯示具有 BCB 標籤的文章。 顯示所有文章

2018年8月23日 星期四

BCB 筆記11 (ComboBox OnChange)

有時候會希望 ComboBox Change 的時候

Grid 能自動更新,但 ComboBox OnChange() 似乎事件較弱

所以 OnChange() 執行後,Grid 並沒有立即更新

你必須點 Grid 一下才會更新,當然一定有正規解法

但我很急無法深入研究,所以用這個邪門歪道


1. 首先創一個 Button1 並設定 OnClick 事件 (為了美觀你可以設Button1隱藏)

void __fastcall TMainForm::Button1Click(TObject *Sender)
{
    Grid->Refresh();
}

2. 在你想要的 ComboBox OnChange() 改為 Button1Click()


參考資料 : 著急的我

2018年8月22日 星期三

BCB 筆記10 (Grid 載圖片)

表格填圖片
下面示範 DrawGrid 填圖片 ( 其實 StringGrid 也可以 )

void __fastcall TMainForm::DrawCell(TObject *Sender, int ACol, int ARow, TRect &Rect, TGridDrawState State)
{
    TDrawGrid *drawgrid = dynamic_cast<TDrawGrid *>(Sender);

    Bitmap->LoadFromFile(ExtractFilePath(Application->ExeName)+__PicturePath+"123.bmp");

    drawgrid->Canvas->Draw(Rect.Left, Rect.Top, Bitmap);

    delete Bitmap;
}

依照圖片大小的方法

    drawgrid->Canvas->StrenchDraw(TRect ,Bitmap);

參考資料
1. 我
2. https://bbs.csdn.net/topics/30220802

2018年7月1日 星期日

BCB 筆記9 (String Replace)

既然使用 BCB 作為開發工具
不免俗就會常常使用他們的 String
這裡介紹 BCB 取代字串的方法
StringReplace(const UnicodeString Source, const UnicodeString OldPattern, const UnicodeString NewPattern, TReplaceFlags Flags);


    String Str;
    TReplaceFlags rf = TReplaceFlags()<<rfReplaceAll;
    Str = StringReplace(Str, L"@", L"\n", rf);


這裡的 TReplaceFlags 有兩種
rfReplaceAll -> 有這個參數會取代全部,無則只取代第一個
rfIgnoreCase -> 有這個參數會無視大小寫,無則會分辨大小寫

參考資料
http://www.cppfans.com/cbknowledge/reference/strings/stringreplace.asp

BCB OLE操作EXCEL(3)

在用 OLE 操作 Excel 時
有可能會遇到剪貼簿裡的資料過大
導致關閉 Excel 時跳出視窗警告
"是否放棄剪貼簿裡的資料"

要避開的話通常會用關閉 DisplayAlert 的方法來避免
但我常常失敗,原因不明。

所以給失敗的朋友另一個辦法
在 Excel 關閉前複製一格 避免剪貼簿裡資料過多跳出視窗


void __fastcall Excel::Close_2(){
    Exc.Range = Exc.WorkSheet.OlePropertyGet("Cells", 1, 1);
    Exc.Range.OleFunction("Copy");
    Exc.WorkBook.OleFunction("Close", false);
    Exc.App.Exec(Procedure("Quit"));
}

上一篇:
BCB OLE操作EXCEL (2)

2018年6月10日 星期日

BCB 筆記8 (Compile)

我在寫程式的時候
偶爾會想寫個固定字串在 Header (路徑之類的)
但這會在 Compile 上造成很大的負荷
Cannot create pre-compiled header: initialized data in header
因為我的 Header 都寫在一起


    const String __SavePath = "Save\\";
    const String __NameCardPath = "NameCard\\";
    const String __PicturePath = "Pic\\";

所以 Header 必須分開
但最好是改讀檔的

但我因為這個發現了一個講解 Compile 的網頁
在此留個紀錄
http://bcbjournal.org/articles/vol4/0005/Pre-compiled_header_tips.htm

BCB 筆記7 (StrToInt)

報告在製作時,一定會遇到要字串轉數字
在 BCB 裡有方便的函式

常見的有

    String str = "123"
    int x = StrToInt(str);
    float y = StrToFloat(str);

但有時候不一定可以轉成數字
這時就可用

    String str = "@123"
    int x;
    float y;
    bool z;
    z = TryStrToInt(str, x);
    z = TryStrToInt(str, y);

2018年6月3日 星期日

BCB 筆記6 (Sender)

說來慚愧,但我很後面才知道這東西
BCB 設計按鈕不外乎 TButton TBitBtn TSpeedButton

但按鈕通常邏輯差不多,只是因為傳的值不一樣而用不同 Button
然後程式碼變成這樣


void __fastcall TMainForm::TButton1Click(TObject *Sender)
{
    MyButtonFunction("TButton1");
}

void __fastcall TMainForm::TButton2Click(TObject *Sender)
{

    MyButtonFunction("TButton2");
}

void __fastcall TMainForm::TButton3Click(TObject *Sender)
{

    MyButtonFunction("TButton3");
}
但你其實可以

void __fastcall TMainForm::ButtonClick(TObject *Sender)
{
    TControl *btn = dynamic_cast<TControl *>(Sender);
    MyButtonFunction(btn->Name);
}
然後再去修改三個 Button 的 OnClick 指向 ButtonClick
這裡為什麼用 TControl 因為一次就可以相容三種 Button
用了半年BCB才知道...

BCB 筆記5 (TValueListEditor)

轉報告下一步就是自動產生報告
要自動產生報告,不外乎就是填表格。

你可以用 DrawGrid 或 StringGrid 來製作表格
但我認為 DrawGrid 和 StringGrid 都是完成度很高的元件
完成度很高代表若目的與設計方向不同,用起來就會綁手綁腳
要覆寫很多功能或者沒有與你目的相同的東西

我想當初 Grid 就是來完成表格,不是給你填,
所以在填值方面不會有太多方便的功能。
填表格通常會想要用下拉式表單 ( ComboBox )
網路上找想用 Grid 來做下拉式表單不外乎兩種
1. 創一個 ComboBox 但"位置"在 Grid 的該 Cell 上
2. 在該 Cell 真的創一個 ComboBox

但我兩種都不用
我這裡要介紹的元件是 TValueListEditor 來 Implement 我要給填的表格
TValueListEditor 只有兩個 Column 一個 Key 和 Value
所以要三欄的你只好乖乖用他給 Grid 元件,或者用CustomGrid 自己做一個 Grid

但 TValueListEditor 她有 EditStyle 可改,讓你的表格更靈活

void __fastcall MyValueListEditorClass::setDropList(TValueListEditor* List, int index, TStringList* li){
    List->ItemProps[index]->EditStyle = esPickList;
    List->ItemProps[index]->PickList = li;
    List->ItemProps[index]->ReadOnly = true;
}
我將 EditStyle 變成 esPickList 就等於是下拉式表格
表格內容就是 PickList (TStringList*)
我覺得比用 Grid 方便許多,結果如下
有些人(我)會想刪掉 TValueListEditor 上面的 FixRow
但是我找了很多方法都不行,最後只能開大絕

    MyValueListEditor->RowHeights[0] = 0;
輕鬆!!!

2018年5月6日 星期日

BCB 筆記4 (DrawText)

在 BCB 裡設計表格類的東西
幾乎都是從 TCustomGrid 繼承而來
在填入表格值都是用 DrawText 來填值
而我們要改變一些東西,例如文字置中
就要自己下 DrawText 的參數

首先第一步,把 DefaultDrawing 的值改為 Fault
不改的話會 DrawText 兩次,造成重疊

第二步改寫 OnDrawCell

void __fastcall TMainForm::LGridDrawCell(TObject *Sender, int ACol, int ARow, TRect &Rect, TGridDrawState State)
{
    TStringGrid *vle = dynamic_cast<TStringGrid *>(Sender);
    int flag = DT_WORDBREAK+DT_CENTER+DT_VCENTER+DT_SINGLELINE;
    vle->Canvas->FillRect(Rect);
    vle->Canvas->Font->Size = 11;
    vle->Canvas->Font->Style = TFontStyles() << fsBold;
    vle->Canvas->Pen->Color = clBlack;
    vle->Canvas->Rectangle(Rect);
    String Str = vle->Cells[ACol][ARow];
    DrawText(vle->Canvas->Handle, Str.w_str(),Str.Length(), &Rect, flag);
}


首先要通用的話,就必須用 Sender 來判斷呼叫的 TStringgrid
再來調整 Flag 來改寫置左中右,上下置中似乎只對單行有作用
接下來就常見的 Font 的操作,最後 DrawText 便大功告成

BCB 筆記3 (TSpeedButton)

在 BCB 裡 Button 我常用的是 TSpeedButton

1. 可以載入圖片( TButton不行 )。
2. TSpeedButton 屬性裡有 GroupIndex 可以集合一群 TSpeedButton 成一個群組,同個群組後,
    一個群只能有一個被選取,被選取的 TSpeedButton 的 Down 值為 TRUE ,為選取則為
    FALSE。
3. 有 FLAT ( 滑鼠移上去會有浮起來的效果 ),對於單人開發的程式,這可以讓你的 Button 看
    起來比較有質感。

2018年5月1日 星期二

BCB OLE操作EXCEL(2)

BCB 操作 EXCEL、WORD ( OLE的應用 )


有時候再操作 EXCEL 和 WORD 的時候,有可能會要應用到 MultiProcess 的概念
但真正需要的地方很少,我自己是用偷懶的方式來避開,
因為互相搶奪導致資料錯誤出現的機率微乎其微。
下面介紹一些我常碰到的錯誤
bool __fastcall JunYe_Word::getDataTable(int index){
    Variant Range;
    bool flag = true;
    try{
        Range = Wd.DataDoc.OlePropertyGet("Tables").OleFunction("Item",index).OlePropertyGet("Range");
    }catch(EOleSysError *e){
        BugReport(L"Ranging Fail !! This Word doesn't have No."+IntToStr(index)+" Table.");
        flag = false;
    }
    if(flag){
        Range.OlePropertyGet("Rows").OleFunction("Item",1).OleFunction("Delete");
        Range.OleFunction("Copy");
    }
    return flag;
}
有時候要 Range 但 FAIL,有可能資料錯誤或跳錯誤訊息,且造成程式當掉的機會很大
這時候就會用 Try and Catch 如上面的程式碼來避免
String __fastcall Excel::getCellValue(int row, int column){
    String data;
    Variant temp;
    try{
        temp = Exc.WorkSheet.OlePropertyGet("Cells", row, column).OlePropertyGet("Value");
        if(VarType(temp) != varError){
            data = temp;
        }
    }catch(EOleSysError *e){
        BugReport(L"The Cell Can't transmit to OleStr");
    }
    return data;
}
這個段程式是防止吃 EXCEL CELL的值時,會導致 Can't transmit to OleStr 的狀況, 不是吃錯值,而是格子可能是#FFFFFF之類的東西,你直接用上述的data(String)去接會錯 Try and Catch 也擋不了( 我自己試擋不了 ),這時我用多了一層判斷, 用 VarType 去檢查 CELL 值是否能轉 OleStr。

上一篇:
BCB OLE操作EXCEL (1)
下一篇:

2018年4月8日 星期日

BCB 筆記2 (TDateTime)

BCB TDateTime 時間操作及應用

在 BCB 裡有關時間的操作幾乎都是與 TDateTime 這個 Class 相關
若找不到相關資料可以用 BCB 的 HELP
( 游標移到要查詢的函式或Class 並按 F1 )

介紹幾個個人有在用的函式
TDateTimePicker->DateTime = Now();
TDateTimePicker->DateTime.DateTimeString();
TDateTimePicker 是常用的 BCB(VCL)元件
可以讓使用方便選擇日期+防呆

String date = "2018/4/8";
StrToDate(date);
將字串轉為 TDateTime 格式
double(TDateTimePicker1->DateTime)-double(TDateTimePicker2->DateTime)
直接代入double() 就可使 TDateTime 量化
這裡 double() 後的數值基本單位是天
1.5 = 一天半

參考資料
1. http://yanphph.blogspot.tw/2009/01/bcb-vcl.html
2. http://cshartuc.blogspot.tw/2016/10/bcb.html

2018年4月1日 星期日

BCB 筆記1 (MessageBox、ComboBox)

寫有介面的程式時常會需要跳出訊息
這裡介紹Application->MessageBox int MessageBox(const char* Text, const char* Caption, int Flags);

這裡沒啥好講的
想寫的幾乎都會變照抄網上的東西,所以就給連結當備份吧
1. http://yanjuns.blogspot.tw/2015/06/cbuilder-vcl.html
2. http://nelson.pixnet.net/blog/post/217684-%5Bbcb%5D-messagebox-%E7%9A%84%E5%8F%83%E6%95%B8%E8%AA%AA%E6%98%8E


如何令 ComboBox 顯示的字不會被更改

答案就是將 ComboBox style 屬性改為 csDropDownList
因為我總是用 BCB10 給的元件去設定 ( Object Inspector )
所以再寫新程式的時候,總忘記當初怎改的
( 因為公司並不會一直要求我去寫資料彙整的程式,久久寫一次 )

令 ComboBox 顯示的字不會被更改

深入了解 ComboBox 後來發現另一招
當 ComboBox 顯示框文字被修改時
會自動尋找是否為 ComboBox 其中一個 Item
是 ItemIndex 修改為該Item 的
否 ItemIndex = -1
此為 BCB10 程式碼
int tempindex;
void __fastcall TMainForm::CSTestSiteComboBoxChange(TObject *Sender)
{
    if(CSTestSiteComboBox->ItemIndex == -1){
        CSTestSiteComboBox->ItemIndex = tempindex;
    }
    tempindex = CSTestSiteComboBox->ItemIndex;
}
如上所示
文字被修改後若不屬於原有 Item (也就是ItemIndex == -1)
修改回來後達到類似無法修改的效果
通常不給修改是為了防呆
所以只能顯示範疇內的東西也是防呆的一種

BCB OLE操作EXCEL(1)

BCB 操作 EXCEL、WORD ( OLE的應用 )


之前有講工作關係需要彙整報告,報告不外乎 WORD、EXCEL、PDF檔

程式要操作 WORD、EXCEL 可以靠微軟的
COM(Component Object Model)或 .NET Framework.
照理說應該要用 .NET Framework ( 比較潮?? ) 但是公司前輩使用的是 COM
新人啥都不懂乖乖跟著學就對了,其實也不知道兩者實際差異
因為從來沒試過另外一種XD

在 COM 的基礎下,OLE ( Object Linking and Embedding )就是我們要用的技術
簡單來說就是把應用程式 ( EXCEL、WORD ) 物件化後給軟體使用
所以在這基礎下達到操作 EXCEL、WORD 和兩者間的溝通操作

這裡使用的 IDE 是 BCB10 拿 EXCEL 作範例

#include "Comobj.hpp" //操作EXCEL
struct _Excel
{
        Variant App;
        Variant WorkBooks;
        Variant WorkBook;
        Variant WorkSheets;
        Variant WorkSheet;
};
首先宣告 Variant 去承接OLE的EXCEL物件
Excel::Excel(){
        Exc.App = CreateOleObject("Excel.Application");
        Exc.App.OlePropertySet("Visible", true);
        Exc.WorkBooks = Exc.App.OlePropertyGet("Workbooks");
}
void __fastcall Excel::Open(AnsiString path){
        Exc.WorkBook = Exc.WorkBooks.OleFunction("Open", OleStr(path));
        Exc.WorkSheets = Exc.WorkBook.OlePropertyGet("Worksheets");
        Exc.WorkSheet = Exc.WorkSheets.OlePropertyGet("Item", 1);
}
void __fastcall Excel::Close(){
        Exc.WorkBook.OleFunction("Close", true);
        Exc.App.Exec(Procedure("Quit"));
}
這裡我分三個FUNCTION 來模擬平時操作EXCEL的狀態( 對我來說直觀好理解 )
constructor 產生EXCEL物件,並開啟工作簿集合( 工作簿想像是EXCEL的外框 )
open            開啟路徑的EXCEL,並在工作表集合要編號為"1"的工作表
close            關閉工作簿,這裡第一行 CODE 代表意義是不儲存就關閉

這裡有個重要東西先講
OLE 物件吃的是 Wide String,這裡用的是萬能的 OleStr() 轉成 Wide String
我從 BCB10 的 UnicodeString 轉過去吃盡苦頭
這時去問了那個唯一可以問的前輩才知道有這個函式,那時真覺得他是活菩薩。
關於 Wide String 和 UnicodeString 的轉換以後再寫一篇

( PS 以下是我的體感,有錯我道歉
關於 OLE 網路上的資源並沒很多
第一個 BCB10 沒人用 (沒有當初BCB6那麼猛),要用都用 Visual C++ 去寫
第二個 OLE 也是一個快被替換的東西
所以用 BCB10 去寫這東西,上網查都是 BCB6 的CODE
所以要注意的是 BCB6 跟 BCB10 字串的差異 )


下一篇:
BCB OLE操作EXCEL (2)

參考來源:
1. http://skybow.pixnet.net/blog/post/98858843-%5Bbcb%5D%E7%94%A8c%2B%2B-builder%E6%8E%A7%E5%88%B6excel%E6%AA%94%E6%A1%88%E8%AE%80%E5%8F%96
2. https://zh.wikipedia.org/wiki/%E7%BB%84%E4%BB%B6%E5%AF%B9%E8%B1%A1%E6%A8%A1%E5%9E%8B
3. https://zh.wikipedia.org/wiki/%E5%AF%B9%E8%B1%A1%E9%93%BE%E6%8E%A5%E4%B8%8E%E5%B5%8C%E5%85%A5

2018年3月29日 星期四

BCB 選擇路徑(資料夾)

BCB 選擇路徑(資料夾)


工作關係要將各式各樣的資料彙整並輸出
各式各樣的資料都放在同一目錄下
所以在設計程式就必須設計可以給使用者選擇目錄
但BCB10似乎沒有這種元件
(其實有 DirectoryListBox 但我駕馭不了)

於是Google發現大家用的是 SelectDirectory();
網路上大大們說有 2 種版本

Boolean SelectDirectory(AnsiString Directory, TSelectDirOpts Options, Longint HelpCtx);
Boolean SelectDirectory(const AnsiString Caption, const BSTR Root, AnsiString Directory, TSelectDirExtOpts Options = [sdNewUI], TWinControl * Parent = nil);

一個是 Windows 的對話框,一個是 BCB 自己的
但我試不出來兩個似乎都長一樣
不知道是 BCB10 的改動還是我用錯

以下是程式碼 ( 第2種版本 )
#include <vcl .filectrl.hpp>
void __fastcall TMainForm::BitBtn1Click(TObject *Sender)
{
    String str;
    TSelectDirExtOpts opt;
    opt += TSelectDirExtOpts()<<sdShowEdit;
    opt += TSelectDirExtOpts()<<sdValidateDir;
    if (SelectDirectory(L"Please Select a Directory", L"", str, opt, this))
        LabeledEdit1->Text = str;
}

SelectDirectory 共輸入了 5 個參數

第一個 Caption = 對話框顯示的字

第二個 Root = 根路徑

第三個 Directory = 選擇的字串

第四個 Options = 對話框樣式

第五個 不清楚,自己理解是 選擇 this 等於我按"這個" Button 這元件就會跳出來

其中 TSelectDirExtOpts 參數可以參考官方文件


參考資料
http://hcl123.blogspot.tw/2012/09/using-open-directory-dialog-box-in-bcb.html

http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/delphivclwin32/FileCtrl_SelectDirectory@string@TSelectDirOpts@Longint.html

BCB Debug

BCB Debug


因為工作關係接觸了 BCB10
這是我人生中第一次學 C++
頁面打開其實不難理解但仍然迷茫了一星期
( 公司只有一個人會,不好意思一直煩他 )

雖然有強大的斷點功能
但我還是不太會用,應該說不習慣
加上我寫的都是小程式
所以我選擇寫一個TXT檔 來記錄LOG
程式碼如下
void BugReport(AnsiString msg)
{
    AnsiString Path = ExtractFilePath(Application->ExeName);
    Path.cat_sprintf("DeBug.txt");
    FILE *fp = fopen(Path.c_str(), "a+");
    if(!fp)return;
    fprintf(fp, "%s\n", msg);
    fclose(fp);
}

至於為什麼用 AnsiString
因為網路上大大們分享的程式碼都是 BCB6
也就是他們的 String 等於 AnsiString
而 BCB10 的 String 等於 UnicodeString
兩者有啥不同,我想痛過就知道

Popular Posts