2013/06/14

ClientDataSet上使用GROUP BY篩選

ClientDataSet對已經收到的資料集是不能再下SQL語法篩選的。

不過,把GROUP BY的邏輯想通應該也可以如法泡製。

直接把結果轉出來吧!

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