Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[13.58.151.231] |
|
Сообщ.
#1
,
|
|
|
Разрабатываю потомка TStringGrid с ComboBox в нескольких подряд идущих столбцах с одинаковыми списками
Вроде почти все работает, но список при нажатии кнопки ComboBox-а не выпадает, приходится действовать только стрелками вверх / вниз для изменения значения Сейчас решаю проблему с передачей фокуса из ComboBox-а в StringGrid - тоже пока работает некорректно Помогите, пожалуйста, разобраться. И еще одна проблема - каждый раз при входе в ComboBox вызывается обработчик Grid.OnExit, а его я использую для анализа и сохранения данных из таблицы в своих переменных. Есть возможность отключить обработку OnExit, если управление передается не на "внешний" компонент, а на "внутренний" ComboBox ? unit TitleGrid; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Grids, stdctrls,Math; TNumComboGrid = class(TStringGrid) private fCB_FirstCol: integer; fCB_LastCol: integer; fCB_Items: TStringList; fCB: TComboBox; // Компонент TComboBox protected { Protected declarations } procedure FixObjPosn(vCol, vRow: LongInt); // Рисование TComboBox в ячейке function Is_ColCombo(ACol:integer):boolean; // Возвращает признак, что в колонке ACol есть TComboBox procedure CB_KeyDown(Sender: TObject; var Key: Word;Shift: TShiftState); // Реакция на клавиши в ComboBox procedure CB_Exit(Sender: TObject); procedure DrawCell(ACol, ARow: Longint; ARect: TRect; AState: TGridDrawState);override; procedure DoEnter; override; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; published // Назначается в design-time : property CB_FirstCol: integer read fCB_FirstCol write fCB_FirstCol; // Первая колонка с TComboBox property CB_LastCol: integer read fCB_LastCol write fCB_LastCol; // Последняя колонка с TComboBox property CB_Items: TStringList read fCB_Items write fCB_Items; // Список значений для TComboBox.Items; end; implementation constructor TNumComboGrid.Create(AOwner: TComponent); var i:integer; begin inherited; RowCount:= 2; fCB_Items:= TStringList.Create; fCB:= TComboBox.Create(AOwner); fCB.Parent:= Self; //или AOwner as TWinControl; - Тогда список выпадает, но возникают другие проблемы fCB.Style:= csDropDownList; fCB.Visible:= false; fCB.OnKeyDown:= CB_KeyDown; fCB.OnExit:= CB_Exit; end; destructor TNumComboGrid.Destroy; var i,j:integer; begin fCB_Items.Free; fCB.Free; inherited; end; procedure TNumComboGrid.CB_Exit(Sender: TObject); // Хочу сдвигаться на следующую колонку begin Cells[Col,Row]:= fCB.Items[fCB.Itemindex]; if Col<ColCount-1 then Col:= Col+1 else begin Col:=1; if Row<RowCount-1 then Row:= Row+1 else Perform(WM_NEXTDLGCTL, 0, 0);//Row:= FixedRows; end; fCB.Visible:= false; SetFocus; SelectCell(Col,Row); end; procedure TNumComboGrid.CB_KeyDown(Sender: TObject;var Key:Word; Shift: TShiftState); begin if (Key=VK_RETURN) or (Key=VK_TAB) or (Key=VK_RIGHT) then begin Key:= 0; CB_Exit(Sender); end else inherited; end; procedure TNumComboGrid.DoEnter; // Решаю проблему с передачей фокуса в TStringGrid begin inherited; if ((Col=0) and (Row=0)) or ((Col=FixedCols) or (Row=FixedRows)) then SelectCell(FixedCols,FixedRows) else SelectCell(Col,Row); end; procedure TNumComboGrid.DrawCell(ACol, ARow: Integer; ARect: TRect; AState: TGridDrawState); begin if Is_ColCombo(ACol) and (ARow>=FixedRows) then begin Canvas.FillRect(ARect); canvas.font.style:=canvas.font.style+[fsbold]; DrawText(Canvas.Handle,PChar(Cells[ACol,Arow]),length(Cells[ACol,Arow]),ARect,DT_LEFT); end else inherited; end; procedure TNumComboGrid.FixObjPosn(vCol, vRow: Integer); var Rc: TRect; begin if Is_ColCombo(vCol) then begin Rc := CellRect(vCol, vRow); if Rc.Right = Rc.Left then {ïðÿìîóãîëüíèê ÿ÷åéêè íåâèäèì} fCB.Visible := False else begin InflateRect(Rc, -1, -1); // OffsetRect(Rc, Left + 1, Top + 1);// Требуется сдвиг, только если fCB.Parent - не Self, a AOwner if fCB.Items.Count=0 then begin fCB.Items.Assign(CB_Items); fCB.DropDownCount:= CB_Items.Count+1; end; fCB.BoundsRect := Rc; fCB.ItemIndex:= fCB.Items.IndexOf(Cells[vCol,vRow]); fCB.Visible := True; fCB.SetFocus; end; end; end; function TNumComboGrid.Is_ColCombo(ACol: integer): boolean; var res:boolean; begin Res:= ((CB_FirstCol>0) and (CB_LastCol>0)); if ACol>=FixedCols then Res:= (res and (ACol>=CB_FirstCol) and (ACol<=CB_LastCol)); Result:= res; end; function TNumComboGrid.SelectCell(ACol, ARow: Integer): Boolean; begin Result:= inherited SelectCell(ACol, ARow); if Is_ColCombo(ACol) then FixObjPosn(ACol, ARow); end; end. |
Сообщ.
#2
,
|
|
|
Если TComboBox.Create(Self); - что кажет?
|
Сообщ.
#3
,
|
|
|
Спасибо. Так - лучше, но проблема не решилась.
Возник еще один вопрос: что перехватывает нажатие клавиш <Enter> и <Tab> в ComboBoxe, когда он не в "раскрытом" состоянии (т.е. когда DroppedDown=false)? При отладке установил точки прерывания в обработчиках событий OnKeyDown и OnKeyPress. В фокусе ввода - ComboBox. Давлю <Enter> - не попадаю ни в KeyDown, ни в KeyPress |
Сообщ.
#4
,
|
|
|
Что-то я не допонял, собрал вот этот код в BDS 2007 - все нормально отрабатывает как тебе и нужно:
unit TitleGrid; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Grids, stdctrls, Math; type TNumComboGrid = class(TStringGrid) private fCB_FirstCol: integer; fCB_LastCol: integer; fCB_Items: TStringList; fCB: TComboBox; // Компонент TComboBox FLock: Boolean; protected procedure FixObjPosn(vCol, vRow: LongInt); // Рисование TComboBox в ячейке function Is_ColCombo(ACol:integer):boolean; // Возвращает признак, что в колонке ACol есть TComboBox procedure CB_KeyDown(Sender: TObject; var Key: Word;Shift: TShiftState); // Реакция на клавиши в ComboBox procedure CB_Exit(Sender: TObject); procedure DrawCell(ACol, ARow: Longint; ARect: TRect; AState: TGridDrawState);override; procedure DoEnter; override; function SelectCell(ACol, ARow: Integer): Boolean; override; procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; published // Назначается в design-time : property CB_FirstCol: integer read fCB_FirstCol write fCB_FirstCol; // Первая колонка с TComboBox property CB_LastCol: integer read fCB_LastCol write fCB_LastCol; // Последняя колонка с TComboBox property CB_Items: TStringList read fCB_Items write fCB_Items; // Список значений для TComboBox.Items; end; implementation constructor TNumComboGrid.Create(AOwner: TComponent); var i:integer; begin inherited; RowCount:= 2; fCB_Items:= TStringList.Create; fCB:= TComboBox.Create(Self); fCB.Parent:= Self; //или AOwner as TWinControl; - Тогда список выпадает, но возникают другие проблемы fCB.Style:= csDropDownList; fCB.Visible:= false; fCB.OnKeyDown:= CB_KeyDown; fCB.OnExit:= CB_Exit; end; destructor TNumComboGrid.Destroy; var i,j:integer; begin fCB_Items.Free; fCB.Free; inherited; end; procedure TNumComboGrid.CB_Exit(Sender: TObject); // Хочу сдвигаться на следующую колонку begin Cells[Col,Row]:= fCB.Items[fCB.Itemindex]; if FLock then Exit; if Col<ColCount - 1 then Col:= Col + 1 else begin Col:=1; if Row<RowCount-1 then Row:= Row+1 else Perform(WM_NEXTDLGCTL, 0, 0);//Row:= FixedRows; end; fCB.Visible:= false; SetFocus; SelectCell(Col,Row); end; procedure TNumComboGrid.CB_KeyDown(Sender: TObject;var Key:Word; Shift: TShiftState); begin if (Key=VK_RETURN) or (Key=VK_TAB) or (Key=VK_RIGHT) then begin Key:= 0; CB_Exit(Sender); end else inherited; end; procedure TNumComboGrid.DoEnter; // Решаю проблему с передачей фокуса в TStringGrid begin inherited; if ((Col=0) and (Row=0)) or ((Col=FixedCols) or (Row=FixedRows)) then SelectCell(FixedCols,FixedRows) else SelectCell(Col,Row); end; procedure TNumComboGrid.DrawCell(ACol, ARow: Integer; ARect: TRect; AState: TGridDrawState); begin if Is_ColCombo(ACol) and (ARow>=FixedRows) then begin Canvas.FillRect(ARect); canvas.font.style:=canvas.font.style+[fsbold]; DrawText(Canvas.Handle,PChar(Cells[ACol,Arow]),length(Cells[ACol,Arow]),ARect,DT_LEFT); end else inherited; end; procedure TNumComboGrid.FixObjPosn(vCol, vRow: Integer); var Rc: TRect; begin if Is_ColCombo(vCol) then begin Rc := CellRect(vCol, vRow); if Rc.Right = Rc.Left then fCB.Visible := False else begin InflateRect(Rc, -1, -1); if fCB.Items.Count=0 then begin fCB.Items.Assign(CB_Items); fCB.DropDownCount:= CB_Items.Count+1; end; fCB.BoundsRect := Rc; fCB.ItemIndex:= fCB.Items.IndexOf(Cells[vCol,vRow]); fCB.Visible := True; fCB.SetFocus; end; end; end; function TNumComboGrid.Is_ColCombo(ACol: integer): boolean; var res:boolean; begin Res:= ((CB_FirstCol>0) and (CB_LastCol>0)); if ACol>=FixedCols then Res := (res and (ACol>=CB_FirstCol) and (ACol<=CB_LastCol)); Result := res; end; procedure TNumComboGrid.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin FLock := True; inherited; end; procedure TNumComboGrid.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin inherited; FLock := False; end; function TNumComboGrid.SelectCell(ACol, ARow: Integer): Boolean; begin Result:= inherited SelectCell(ACol, ARow); if Is_ColCombo(ACol) then FixObjPosn(ACol, ARow); end; end. |
Сообщ.
#5
,
|
|
|
У меня под Delphi 7 - не получается. Может быть, это из-за Среды разработки, а может, от того, что у меня
Родитель - не TStringGrid, а свой Grid. Привожу модуль целиком { TTitleGrid 1. Многострочный заголовок колонок таблицы 2. Содержимое заголовка и первой колонки задаются в Design-time (TitlesRow - заголовки строк, TitlesCol - заголовки колонок) 3. Подсказки (Hints) выводятся для каждой колонки (или строки при HintsOnCol=false), и задаются в Design-time Подсказка может быть многострочной, новая строка - символ @ 4. Клавиша ENTER перемещает на след. ячейку (и следующую строку на последней ячейке в строке) 5. Выравнивание рабочих ячеек - по правому краю, заголовка колонок - по центру ,Заголовки строк - по левому краю, или по центру, если выполнен медод Assign_NumRow, заполняющий нулевую колонку номерами строк 6. Ширина первой колонки задается в Design-time (FirstColWidth) 7. Добавлена процедура удаления строки Delete_Row(ARow) TTitleNumGrid 1. Числа в ячейках таблицы округляются до Precissions знаков после запятой 2. Точность округления последних NumLastCol колонок может быть другой, и задается в PrecLastCol. TNumComboGrid Несколько колонок, с CB_FirstCol по CB_LastCol - выпадающий список TComboBox. Содержимое списка задается в CB_Items } unit TitleGrid; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Grids, stdctrls,Math; type TTitleGrid = class(TStringGrid) private fHints: TStringList; // Подсказки fHintsOnCols: boolean; // Подсказки по строкам, или столбцам? function GetFirstCol: Integer; procedure SetFirstCol(const Value: Integer); procedure SetHintsOnCols(const Value: boolean); procedure SetHints(const Value: TStringList); procedure SetTitlesCol(Value: TStrings); function GetTitlesCol: TStrings; procedure SetTitlesRow(Value: TStrings); function GetTitlesRow: TStrings; function GetFirstCol1: Integer; procedure SetFirstCol1(const Value: Integer); protected { Protected declarations } Old_Col:Integer; // Для отслеживания передвижения мыши Old_Row:Integer; // между строками и столбцами StyleCol0: Cardinal; //Стиль колонки N 0 procedure MouseMove(Shift: TShiftState; X, Y: Integer); override; procedure DrawCell(ACol, ARow: Longint; ARect: TRect; AState: TGridDrawState);override; procedure KeyPress(var Key: Char); override; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure Delete_Row(ARow:integer);dynamic;// Удалить строку вместе с подсказками procedure Assign_NumRow; // Записывает в TitlesRow № строки published property Hints: TStringList read fHints write SetHints; Property HintsOnCols: boolean read FHintsOnCols write SetHintsOnCols; property FirstColWidth: Integer read GetFirstCol write SetFirstCol; property FirstCol1Width: Integer read GetFirstCol1 write SetFirstCol1; property TitlesRow: TStrings read GetTitlesRow write SetTitlesRow; // Первая колонка property TitlesCol: TStrings read GetTitlesCol write SetTitlesCol; // Первая строка end; //======================================================== TTitleNumGrid = class(TTitleGrid) private fPrecissions: byte; fNumLastCol: byte; fPrecLastCol: byte; protected { Protected declarations } procedure KeyPress(var Key: Char); override; procedure DrawCell(ACol, ARow: Longint; ARect: TRect; AState: TGridDrawState);override; public procedure Delete_Row(ARow:integer); override; published property Precissions: byte read fPrecissions write fPrecissions; property NumLastCol: byte read fNumLastCol write fNumLastCol; property PrecLastCol: byte read fPrecLastCol write fPrecLastCol; end; //====================================================================== {TNumComboGrid} TNumComboGrid = class(TTitleNumGrid) private fCB_FirstCol: integer; fCB_LastCol: integer; fCB_Items: TStringList; fCB: TComboBox; fCB_OfsX: integer; // Смещения для Rect, если fCB создается fCB_OfsY: integer; // как AOwner, а не Self Col_CB: integer; //Текущая колонка и столбец ComboBox Row_CB: integer; procedure Set_CB_Items(const Value: TStringList); protected { Protected declarations } procedure FixObjPosn(vCol, vRow: LongInt); function SelectCell(ACol, ARow: Longint): Boolean; override; function Is_ColCombo(ACol:integer):boolean; procedure CB_KeyDown(Sender: TObject; var Key: Word;Shift: TShiftState); procedure CB_Change(Sender: TObject); procedure CB_Enter(Sender: TObject); procedure CB_Exit(Sender: TObject); procedure DrawCell(ACol, ARow: Longint; ARect: TRect; AState: TGridDrawState);override; procedure DoEnter; override; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; function Get_CB_Index(Str:string): Integer; // Индекс по строке published property CB_FirstCol: integer read fCB_FirstCol write fCB_FirstCol; property CB_LastCol: integer read fCB_LastCol write fCB_LastCol; property CB_OfsX: integer read fCB_OfsX write fCB_OfsX; property CB_OfsY: integer read fCB_OfsY write fCB_OfsY; property CB_Items: TStringList read fCB_Items write Set_CB_Items; end; procedure Register; implementation //****************************************************** uses StrUtils,DesignIntf; procedure Register; begin RegisterComponents('Art', [TTitleGrid]); RegisterPropertyEditor(TypeInfo(string), TTitleGrid, 'Hint', nil); RegisterComponents('Art', [TTitleNumGrid]); RegisterComponents('Art', [TNumComboGrid]); //RegisterPropertyEditor(TypeInfo(string), TNumComboGrid, 'Hint', nil); //RegisterPropertyEditor(TypeInfo(LongInt), TNumComboGrid, 'RowCount', nil); end; constructor TTitleGrid.Create(AOwner: TComponent); begin inherited; Options:= Options+[goEditing]+[goTabs]; fHints:= TStringList.Create; Old_Col:= -1; Old_Row:= -1; StyleCol0:= DT_LEFT; end; destructor TTitleGrid.Destroy; begin fHints.Free; inherited; end; procedure TTitleGrid.SetTitlesRow(Value: TStrings); var i:integer; begin for i:=1 to Value.Count-1 do if i<RowCount then Cells[FixedCols-1,i]:= Value[i] else if Value[i]<>'' then begin RowCount:= RowCount+1; Cells[FixedCols-1,i]:= Value[i]; end; end; procedure TTitleGrid.SetTitlesCol(Value: TStrings); var i:integer; begin if Value.Count<ColCount then begin for i:=ColCount-1 downto Value.Count+FixedRows do Cells[i,0]:=''; end; for i:=0 to Value.Count-1 do if i<ColCount then Cells[i,0]:= Value[i] else if Value[i]<>'' then begin ColCount:= ColCount+1; Cells[i,0]:= Value[i]; end; end; function TTitleGrid.GetTitlesRow: TStrings; begin result := Cols[FixedCols-1]; end; function TTitleGrid.GetTitlesCol: TStrings; begin result := Rows[0]; end; function TTitleGrid.GetFirstCol: Integer; begin result:= ColWidths[0]; end; procedure TTitleGrid.SetFirstCol(const Value: Integer); begin ColWidths[0]:= Value; end; function TTitleGrid.GetFirstCol1: Integer; begin result:= ColWidths[FixedCols-1]; end; procedure TTitleGrid.SetFirstCol1(const Value: Integer); begin ColWidths[FixedCols-1]:= Value; //if FixedCols=1 then end; procedure TTitleGrid.SetHints(const Value: TStringList); begin fHints.Assign(Value); end; procedure TTitleGrid.SetHintsOnCols(const Value: boolean); begin FHintsOnCols := Value; end; //=========== Рисование заголовков ===================== procedure TTitleGrid.DrawCell(ACol, ARow: Integer; ARect: TRect; AState: TGridDrawState); var Flag: Cardinal; H: integer; begin Canvas.FillRect(ARect); Inc(ARect.Left,3); if (ARow=0) and (FixedRows=1) then begin Dec(ARect.Right,3); canvas.font.style:=canvas.font.style+[fsbold]; Flag:= DT_WORDBREAK or DT_CENTER; H := DrawText(Canvas.Handle,PChar(Cells[ACol,Arow]),length(Cells[ACol,Arow]),ARect,Flag); if H>RowHeights[0] then RowHeights[0] := H; //увеличиваем end else if (ACol=FixedCols-1) then begin canvas.font.style:=canvas.font.style+[fsbold]; if FixedCols=1 then Flag:= StyleCol0 else Flag:= DT_LEFT; end else if ACol=FixedCols-2 then begin canvas.font.style:=canvas.font.style+[fsbold]; Flag:= DT_CENTER; end else begin Flag:=DT_RIGHT; Dec(ARect.Right,3); end; DrawText(Canvas.Handle,PChar(Cells[ACol,Arow]),length(Cells[ACol,Arow]),ARect,Flag); canvas.font.style:=canvas.font.style-[fsbold]; end; //======== Перемещение м/у ячейками по клавише ENTER ======================== procedure TTitleGrid.KeyPress(var Key: Char); begin if Key=#13 then begin if Col < ColCount-1 then {следующая колонка!} Col := Col + 1 else if Row < RowCount-1 then begin {следующая строка!} Row := Row + 1; Col := FixedCols; end else begin {Конец сетки! - Снова перемещаемся наверх!} Row := 1; Col := 1; // или передать управление следующему элементу управления //Perform(WM_NEXTDLGCTL, 0, 0); end; Key:= #00; end; inherited; end; //=========== Показывает Hint для отдельной колонки(строки) ============ procedure TTitleGrid.MouseMove(Shift: TShiftState; X, Y: Integer); var ACol,Arow:integer; s:string; begin inherited MouseMove(Shift,x,y); MouseToCell(x,y,ACol,ARow); if (fHintsOnCols and ((Old_Col<>ACol) and (ACol>FixedCols-1) and (fHints.Count>ACol))) or (not fHintsOnCols and ((Old_Row<>ARow) and (ARow>FixedRows-1) and (fHints.Count>ARow))) then begin Old_Col:= ACol; Old_Row:= ARow; ShowHint:= false; Application.CancelHint; s:= fHints.Strings[ACol]; While Pos('@',s) <> 0 Do s[Pos('@',s)] := #13; Hint:= s; ShowHint:= true; end; end; //==== Удаление строки с соответствующим Hint-ом (при HintsOnCols=false) === procedure TTitleGrid.Delete_Row(ARow: integer); var i:integer; begin if ARow>FixedRows-1 then for i:=Arow to RowCount-2 do begin Rows[i]:= Rows[i+1]; end; if not HintsOnCols and (fhints.Count>ARow) then fHints.Delete(ARow); RowCount:= RowCount-1; end; //======= Заполняет колонку № 0 номерами строки и меняет выравнивание на CENTER procedure TTitleGrid.Assign_NumRow; var i:integer; begin StyleCol0:= DT_CENTER; for i:=1 to RowCount-1 do Cells[0,i]:= IntToStr(i); end; {================== TTitleNumGrid ============================} procedure TTitleNumGrid.Delete_Row(ARow: integer); begin inherited; end; procedure TTitleNumGrid.DrawCell(ACol, ARow: Integer; ARect: TRect; AState: TGridDrawState); var r:real; s:string; p:byte; begin if (ACol>=FixedCols) and (ARow>=FixedRows) then begin Canvas.FillRect(ARect); s:=Cells[ACol,ARow]; if (s='') or (s=' ') then s:= '0'; try r:=StrToFloat(s); if abs(r)<0.00001 then r:=0; if ACol<=ColCount-fNumLastCol then p:= -fPrecissions else p:=-fPrecLastCol; s:= FloatToStr(RoundTo(r,p)); dec(ARect.Right,3); DrawText(Canvas.Handle,PChar(s),length(s),ARect,DT_RIGHT); except on EConvertError do exit; end; end else inherited; end; procedure TTitleNumGrid.KeyPress(var Key: Char); begin if Key=',' then Key:= '.' else if not ((Key='.') or (Key='-') or ((Key>='0') and (Key<='9')) or (Key=#13) or (Key=#08) or (Key=#09)) then begin Beep;Key:=#00; end; inherited; end; //========================= TNumComboGrid ================================ constructor TNumComboGrid.Create(AOwner: TComponent); var i:integer; begin inherited; RowCount:= 2; fCB_Items:= TStringList.Create; fCB:= TComboBox.Create(Self {AOwner}); fCB.Parent:= Self; //AOwner as TWinControl; //Self; //fCB.Style:= csDropDownList; // Значения - ТОЛЬКО из списка, поиск по нескольким начальным // буквам, а не по одной SendMessage(GetWindow(fCB.Handle,GW_CHILD), EM_SETREADONLY, 1, 0); fCB.Visible:= false; fCB.OnKeyDown:= CB_KeyDown; fCB.OnChange:= CB_Change; fCB.OnEnter:= CB_Enter; fCB.OnExit:= CB_Exit; end; destructor TNumComboGrid.Destroy; var i,j:integer; begin fCB_Items.Free; fCB.Free; inherited; end; procedure TNumComboGrid.CB_Change(Sender: TObject); begin //if (Col_CB<>0) and (Row_CB<>0) then Cells[Col_CB,Row_CB]:= fCB.Items[fCB.Itemindex]; end; procedure TNumComboGrid.CB_Enter(Sender: TObject); begin Col_CB:= Col; Row_CB:= Row; end; procedure TNumComboGrid.CB_Exit(Sender: TObject); begin if Col=Col_CB then if Col<ColCount-1 then fCB.Visible:= false; SelectCell(Col,Row); end; procedure TNumComboGrid.CB_KeyDown(Sender: TObject;var Key:Word; Shift: TShiftState); begin if (Key=VK_RETURN) or (Key=VK_TAB) or (Key=VK_RIGHT) or (Key=VK_LEFT) then begin if (Key=VK_LEFT) or (ssShift in Shift) then begin if Col_CB<=FixedCols then exit; Col:= Col_CB-1; end else begin if Col_CB<ColCount-1 then Col:= Col_CB+1 else begin Col:=1; if Row_CB<RowCount-1 then Row:= Row_CB+1 else Perform(WM_NEXTDLGCTL, 0, 0);//Row:= FixedRows; end; end; Key:= 0; //fCB.Visible:= false; SetFocus; end; end; function TNumComboGrid.SelectCell(ACol, ARow: Integer): Boolean; begin Result:= inherited SelectCell(ACol, ARow); if Is_ColCombo(ACol) then FixObjPosn(ACol, ARow); end; procedure TNumComboGrid.DoEnter; begin inherited; if ((Col=0) and (Row=0)) or ((Col=FixedCols) or (Row=FixedRows)) then SelectCell(FixedCols,FixedRows) else SelectCell(Col,Row); end; procedure TNumComboGrid.DrawCell(ACol, ARow: Integer; ARect: TRect; AState: TGridDrawState); begin if Is_ColCombo(ACol) and (ARow>=FixedRows) then begin Canvas.FillRect(ARect); canvas.font.style:=canvas.font.style+[fsbold]; DrawText(Canvas.Handle,PChar(Cells[ACol,Arow]),length(Cells[ACol,Arow]),ARect,DT_LEFT); end else inherited; end; procedure TNumComboGrid.FixObjPosn(vCol, vRow: Integer); var Rc: TRect; begin if Is_ColCombo(vCol) then begin Rc := CellRect(vCol, vRow); if Rc.Right = Rc.Left then {прямоугольник ячейки невидим} fCB.Visible := False else begin InflateRect(Rc, -1, -1); OffsetRect(Rc, Left + fCB_OfsX, Top + fCB_OfsY); if fCB.Items.Count=0 then begin fCB.Items.Assign(CB_Items); fCB.DropDownCount:= CB_Items.Count+1; // ReadOnly 0 - выключить SendMessage(GetWindow(fCB.Handle,GW_CHILD), EM_SETREADONLY, 1, 0); end; fCB.BoundsRect := Rc; fCB.ItemIndex:= fCB.Items.IndexOf(Cells[vCol,vRow]); fCB.Visible := True; fCB.SetFocus; end; end; end; function TNumComboGrid.Get_CB_Index(Str: string): Integer; begin Result:= CB_Items.IndexOf(Str); end; function TNumComboGrid.Is_ColCombo(ACol: integer): boolean; var res:boolean; begin Res:= ((CB_FirstCol>0) and (CB_LastCol>0)); Res:= (res and (ACol>=CB_FirstCol) and (ACol<=CB_LastCol)); Result:= res; end; procedure TNumComboGrid.Set_CB_Items(const Value: TStringList); var i:integer; begin fCB_Items.Clear; for i:=0 to Value.Count-1 do fCB_Items.Add(Value.Strings[i]); end; end. |
Сообщ.
#6
,
|
|
|