2013/06/13

Delphi繼承的寫法

底下的連結提供了相當多的解法,有時需要改裝一下TCustomForm時可以來參考使用。

資料來源:Delphi/pascal: overloading a constructor with a different prototype

Delphi 2009 raises Exception in DBX: Unknown Driver XXX

在Design Mode下使用TSQLConnection,設定完成後也可以正常連線,可是在Runtime硬是出現「Unknown Driver: MSSQL」。

其實這只要在uses區手動加入「DBXDynalink」,就可以用了。

資料來源:Delphi 2009 raises Exception "Unknown Driver: Devart..."

2013/06/10

EAccessViolation in function CreateProcess in Delphi 2009

很有趣的,我也遇到了這件事情,明明 CreateProcess 這函式在Delphi 7時就正常,到了Delphi 2009就出怪手了。

原因就是出在Unicode……解法轉貼如下:

2013/06/06

DBGrid scrolling (滾動條事件) 生成

C++ Builder的DBGrid比較麻煩,可以的話還是從Delphi建一個後再使用帶入使用吧。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
/* JDBGrid.h文件内容 */
//-------------------------------------------------------------------------
#ifndef JDBGridH
#define JDBGridH
//-------------------------------------------------------------------------
#include <SysUtils.hpp>
#include <Classes.hpp>
#include <Controls.hpp>
#include <DBGrids.hpp>
#include <Grids.hpp>
//-------------------------------------------------------------------------
class PACKAGE TJDBGrid : public TDBGrid
{
  enum TDBGridOption{ dgEditing, dgAlwaysShowEditor,
                      dgTitles, dgIndicator, dgColumnResize,
                      dgColLines, dgRowLines, dgTabs,
                      dgRowSelect, dgAlwaysShowSelection,
                      dgConfirmDelete, dgCancelOnExit,
                      dgMultiSelect ,dgThumbTracking,dgMouseWheel};
typedef Set<TDBGridOption,dgEditing,goThumbTracking>  TDBGridOptions;
  private:
    TDBGridOptions FOptions;
  protected:
    TWndMethod DBGridProc;
    TWndMethod DBInplaceEditProc;
    virtual void __fastcall JDBInplaceEditProc(Messages::TMessage &Message);
    virtual void __fastcall JDBGridProc(Messages::TMessage& Message);
    virtual Grids::TInplaceEdit* __fastcall CreateEditor(void);
    void __fastcall SetOptions(TDBGridOptions Value);
  public:
    __fastcall TJDBGrid(TComponent* Owner);
    __published:
    __property TDBGridOptions Options = {read=FOptions, write=SetOptions,default=27901};
};
//-------------------------------------------------------------------------
#endif

/* JDBGrid.cpp文件内容 */
//-------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "JDBGrid.h"
#pragma package(smart_init)
//-------------------------------------------------------------------------
static inline void ValidCtrCheck(TJDBGrid *)
{
  new TJDBGrid(NULL);
}
//-------------------------------------------------------------------------
fastcall TJDBGrid::TJDBGrid(TComponent* Owner):TDBGrid(Owner)
{
  short *shortTmp;
  Dbgrids::TDBGridOptions optionsTmp;
  (void*)shortTmp=(void*)&FOptions;
  *shortTmp=27901;
  (void*)shortTmp=(void*)&optionsTmp;
  *shortTmp=3325;
  TDBGrid::Options=optionsTmp;
  DBGridProc=WindowProc;
  WindowProc=JDBGridProc;
}
//-------------------------------------------------------------------------
void __fastcall TJDBGrid::SetOptions(TDBGridOptions Value)
{
   short *pValue,*pOp,*pFOp,saveValue;
   Dbgrids::TDBGridOptions DBGridOptions;
   (void*)pValue=(void*)&Value;
   (void*)pOp=(void*)&DBGridOptions;
   (void*)pFOp=(void*)&FOptions;
   *pOp=*pValue & 0x1fff;
   TDBGrid::Options=DBGridOptions;
   DBGridOptions=TDBGrid::Options;
   *pFOp=*pOp | (*pValue & 0x6000);
}

//-------------------------------------------------------------------------
void __fastcall TJDBGrid::JDBInplaceEditProc(Messages::TMessage &Message)
{
   switch (Message.Msg)
   {
      case WM_MOUSEWHEEL:
         if(Options.Contains(dgMouseWheel))
         {
            if (DataLink->Active)
            {
               if (Message.WParam<0)
               {
                if (DataLink->DataSet->RecNo<DataLink->DataSet->RecordCount)
                DataLink->DataSet->RecNo++;
               }
               else
               {
                  if (DataLink->DataSet->RecNo>1)
                     DataLink->DataSet->RecNo--;
               }
            }
            if (!Options.Contains(dgAlwaysShowEditor))
               EditorMode=false;
            return;
         }
      break;
   }
   DBInplaceEditProc(Message);
}
//-------------------------------------------------------------------------
Grids::TInplaceEdit* __fastcall TJDBGrid::CreateEditor(void)
{
   TInplaceEdit *tmp;
   tmp=TDBGrid::CreateEditor();
   DBInplaceEditProc=tmp->WindowProc;
   tmp->WindowProc=JDBInplaceEditProc;
   return tmp;
}
//-------------------------------------------------------------------------
void __fastcall TJDBGrid::JDBGridProc(Messages::TMessage& Message)
{
   switch (Message.Msg)
   {
      case WM_VSCROLL:
      case WM_HSCROLL:
         if (Options.Contains(dgThumbTracking))
            if (Message.WParamLo==5)
            {
               DBGridProc(Message);
               Message.WParamLo=4;
               DBGridProc(Message);
               Message.WParam=8;
            }
         break;
      case WM_MOUSEWHEEL:
         if(Options.Contains(dgMouseWheel))
         {
            DBGridProc(Message);
            if (DataLink->Active)
            {
               if (Message.WParam<0)
               {
                 if (DataLink->DataSet->RecNo<DataLink->DataSet->RecordCount)
                   DataLink->DataSet->RecNo++;
               }
               else
               {
                 if (DataLink->DataSet->RecNo>1)
                   DataLink->DataSet->RecNo--;
               }
            }
            if (!Options.Contains(dgAlwaysShowEditor))
              EditorMode=false;
            return;
         }
      break;
   }
   DBGridProc(Message);
}
//-------------------------------------------------------------------------
namespace Jdbgrid
{
        void __fastcall PACKAGE Register()
        {
                 TComponentClass classes[1] = {__classid(TJDBGrid)};
                 RegisterComponents("Samples", classes, 0);
        }
}
//-------------------------------------------------------------------------


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/* 技巧三,行列不同颜色时,交叉部位颜色的设置。
   如图:在交叉部位使用行列颜色的alpha混合。
   响应TDBGrid的OnDrawColumnCell事件如下:*/
void __fastcall TForm1::JDBGrid1DrawColumnCell(TObject *Sender,
      const TRect &Rect, int DataCol, TColumn *Column,
      TGridDrawState State)
{
  int recordNo,tmpInt;
  if (JDBGrid1->DataSource->DataSet->Active)
  {
    recordNo=DataCol=JDBGrid1->DataSource->DataSet->RecNo % 10;
    if (recordNo ==0 || recordNo>5 )
       JDBGrid1->Canvas->Brush->Color=0xb0b0ff;
    else
       JDBGrid1->Canvas->Brush->Color=0xffe0e0;
    tmpInt=Column->Color;
    if (tmpInt!=clWindow)
    {
        int R1,G1,B1,R2,G2,B2,rgbTmp;
        int alpha=60;
        rgbTmp=JDBGrid1->Canvas->Brush->Color;
        R1=tmpInt & 0xff;
        G1=(tmpInt & 0xff00)>>8;
        B1=(tmpInt & 0xff0000)>>16;
        R2=rgbTmp & 0xff;
        G2=(rgbTmp & 0xff00)>>8;
        B2=(rgbTmp & 0xff0000)>>16;
        R1=(R1*alpha+R2*(256-alpha))>>8;
        G1=(G1*alpha+G2*(256-alpha))>>8;
        B1=(B1*alpha+B2*(256-alpha))>>8;
        JDBGrid1->Canvas->Brush->Color=(TColor)(R1+(G1<<8)+(B1<<16));
    }
    JDBGrid1->Canvas->FillRect(Rect);
  }
  JDBGrid1->DefaultDrawColumnCell(Rect,DataCol,Column,State);
}


Delphi就相當簡單,直接繼承就可以用了。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
uses Message;
type
  TDBGrid = class(DBGrids.TDBGrid)
  private
    procedure WmVScroll(var Message: TWMVScroll); message WM_VSCROLL;
  end;

  TForm1 = class(TForm)
    DBGrid1: TDBGrid;
    ..

implementation

procedure TDBGrid.WmVScroll(var Message: TWMVScroll);
begin
  if Message.ScrollCode = SB_THUMBTRACK then
    Message.ScrollCode := SB_THUMBPOSITION;
  inherited;
end;


如此一來,DBGrid的滾動條在拉動的過程中,DataSet的RecNo也會跟著一起調整,十分好用的小技巧。


參考來源:

TDBGRID一些小技巧
Delphi dbgrid continuous scrolling
Winapi.Messages.TWMVScroll

2013/05/30

Enabling Virtual Space mode use Notepad++

Delphi有個很好用的編輯功能:

我不會解釋……就是不管上下行字數有無相同,在按了上下鍵後游標都會在同一個位置上下跑。

我一直以為好用的Editor都應該會有這個功能,後來才發現……Notepad++沒有!

之後好久好久終於在Visual Studio看到了這個功能,中文名詞是:
啟用虛擬空間
英文是"Enabling Virtual Space mode"

後來在這個討論串中找到解法,節錄內容如下:
Sort of a hack (sends a window message directly to the Scintilla edit control on startup), but works great:
  1. Install NppExec plugin
  2. Go to Plugins -> NppExec -> Execute
  3. Enter the following code:
    // ensure console stays hidden
    NPP_CONSOLE 0
    
    // enable virtual spaces (cursor past end of line) outside column edit mode
    SCI_SENDMSG 2596 3 0
    
    // SCI_SENDMSG == send message to Scintilla edit control
    // 2596 == the message we're sending is SCI_SETVIRTUALSPACEOPTIONS
    // 3 == send the value (SCVS_RECTANGULARSELECTION | SCVS_USERACCESSIBLE)
    // the default value is 1 (just SCVS_RECTANGULARSELECTION) for
    //   virtual spaces in column select mode only
    // you can find these values by poking around the source code a bit, or
    // see http://www.scintilla.org/ScintillaDoc.html
    
  4. Click the Save button at the bottom, and give the script a name
  5. Now go to Plugins -> NppExec -> Advanced Options
  6. On the right, under "Execute this script when Notepad++ starts", select the script name you just saved
  7. Click OK, close/reopen Notepad++, and enjoy ;)

這方面還是外國人厲害啊!讚!

2013/05/29

NotePad++ for MetaEditor

『Expert advisor』は、おもしろい!: Notepad++ de MQL4: 『 秀丸エディタをMQL4エディタ(MetaEditor)にする方法 』と言う記事を読んで、面白そうだったのでNotepad++でやってみました。実施範囲は、自動補完・ハイライト・コンパイル作業です。 初めに Notepad++とは notepad++の導入方法な...


很實用的教學  Notepad++也可以寫+編譯MQL4的檔案了!

整理一下資料,方便自己以後使用:

2013/05/28

Thread開發的三兩事

Thread,顧名思義,是很細的線,千萬不要讓大象踩上去。

讓貓自己去玩Thread,必要的時侯請先保護好自己的東西(Synchronize,TCriticalSection,Lock...etc),
再拿不會壞的玩具(Base Type)和牠玩一下下。

玩太久人(UI)會呆掉,所以主要原則就是讓牠自己玩。