Как и обещал - выкладываю способ использования хелперов в Delphi, вместо правки исходников. Представим ситуацию, когда необходимо изменить какой-то базовый класс, для того, чтобы добавить новый функционал (или поправить баги) для всех наследуемых, от него, классов. Например, TStrings. Добавив что-то в него, можно это использовать в TStringList, а с ним и в TMemo, например.
Делая одну программу, понадобилось смоделировать переход по ячейкам VirtualTreeView с помощью кнопки Tab. Перехват Tab-а отдельный разговор =), а вот переход по ячейкам сейчас обсудим.
Дело в том, что при переходе по ячейкам VT сразу вызывает редактирование нода, в связи с чем у меня возникала ситуация, когда на редактирование вызывалась не правильная ячейка. Т.е., если реализуете перемещение по ячейкам сами, делайте примерно так:
with vtGrid do
begin
TreeOptions.MiscOptions := vtGrid.TreeOptions.MiscOptions - [toEditable];
Selected[lNode] := True;
FocusedNode := lNode;
FocusedColumn := lColumn;
TreeOptions.MiscOptions := vtGrid.TreeOptions.MiscOptions + [toEditable];
EditNode(lNode, lColumn);
end;
В таком варианте все работает так, как и ожидается.
P.S.: отметьте для себя еще один момент - очередность присваивания фокуса в дереве - сначала SelectedNode, потом FocusedNode и только после этого FocusedColumn! Только так и никак иначе! В ином случае вас ждут не приятные сюрпризы
НИКОГДА так не делайте!
На, уважаемом мною, сайте увидел ссылку на . Я и до этого с трудом переносил его книги и статьи, но эта статья просто возмутила!
Намного проще изменить стандартный компонент TButton и больше никаких изменений в проекте делать не надо.
Как так можно??? Вместо того, чтобы объяснить новичкам, что это ОЧЕНЬ не желательно, он призывает поступать именно так. Ну в конце-концов - есть хелперы в новых (и, относительно, не новых. например D2006) версиях Delphi.
Я понимаю, что иногда это будет полезно, но такие случаи очень-очень редки. А новички, прочтя подобную статью, будут именно так и поступать. Что-то мне не вериться, что в какой-либо компании, занимающейся разработкой программ и в которой больше одного программиста, будут поступать подобным образом.
Итог - НИКОГДА так не делайте и перестаньте читать Фленова!
В Windows определены специальные, виртуальные коды, для кнопок клавиатуры. Например, VK_Enter, VK_Delete и т.д. Данные коды используются не часто, но все-же используются. Например, в OnKeyUp и в OnKeyDown.
Небольшая функция поможет вам преобразовать данные коды в символы:
function GetCharFromVirtualKey(Key: Word): string; var keyboardState: TKeyboardState; asciiResult: Integer; begin GetKeyboardState(keyboardState); SetLength(Result, 2); asciiResult := ToAscii(key, MapVirtualKey(key, 0), keyboardState, @Result[1], 0); case asciiResult of 0: Result := ''; 1: SetLength(Result, 1); 2:; else Result := ''; end; end;
Пример использования:
procedure TForm1.Memo1KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState) ; begin Self.Caption := GetCharFromVirtualKey(Key) ; end;
Оригинал .
Плохо…
Конкурс просто провалился... Я ни разу не нашел ни одной статьи. Жаль. А ведь хотелось сделать это традицией - ежемесячно проводить конкурс на какую-то определенную тему.
Ресурсы в проекте
Я всегда думал, что для того, чтобы подключить ресурсы (текст, картинки и т.д.) к проекту, надо их скомпилить (brcc32.exe) и подключить ({$R}). А вот сегодня один хороший человек (, спасибо), подсказал, что это совсем не обязательно. Надо просто подключить к проекту (Add to Project) .rc файл, а скомпилиться и прилинкуется он сам. Проверил в D7, D2006. Вот так вот...
Что-то не видно желающих написать пост про VirtualTreeView для конкурса. Жаль...
Ну тогда я сам попробую
. Тем более, что нашелся подходящий повод.
Приведение типов
Мне всегда казалось, что TType(Var) и Var as TType работает одинаково или, в крайнем случае, очень похоже. Так было до не давнего времени.
Вместе со знакомым выясняли одну багу (так и не выяснили причину, кстати):
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils;type
TA = class
function GetResult: Integer; //virtual;
end;TB = class(TA)
function GetResult: Integer; //override;
end;{ TA }
function TA.GetResult: Integer;
begin
Result := 10;
end;{ TB }
function TB.GetResult: Integer;
begin
Result := 20;
end;var
B: TB;begin
B := TB.Create;
WriteLn(IntToStr(TA(B).GetResult));
WriteLn(IntToStr((B as TA).GetResult));ReadLn;
end.
Как по-вашему, что будет выведено, в результате данного кода? Если вы считаете, что будет выведено два раза '10', то вы не угадали. Будет выведено '10' и '20'.
Конкурс
1. Не надо использовать классы.
А зачем? Классы - это вред. Это слишком много кода. Какая защита данных? Какое скрытие методов? Только для себя же пишу. А сам разберусь... Наверное.
Подпись на форуме
Pascal - как англ. язык, I Love You - слова местами не переставишь, всё прямо и понятно. С++ - как русский язык, Я люблю тебя, тебя люблю я, люблю я тебя - уйма вариантов с кучей интонаций. Asm - как китайский язык - одна черточка не в том месте и ты уже не признался в любви, а послал кого-то на йух
А ведь верная мысль...
TList
Последние 2 часа меня мучает один вопрос... Вот код, который обчно пишу я:
type
TMyClass = class
private
FList: TList;
public
constructor Create; override;
destructor Destroy; override;
function Add(AData: TData): Integer;
end;
Т.е., в программе я использую уже не наследник TList, а обертку для TList. В принципе, я понимаю почему так делаю:
1. Нет лишних методов и параметров.
2. Удобный, для меня, вид и код.
3. Что-то еще, уже не помню
В то же время можно все сделать проще:
type
TMyClass2 = class(TList);
Но, во втором случае вижу только один плюс - меньше кода. И один весомый минус - лишние методы, открывающие внутреннее устройство класса, например Count, который часто и не нужен.
Может подскажите, какие еще есть плюсы/минусы у обоих подходов?

Хочу представить еще одну книгу, давно прописавшуюся, у меня, на полке. В принципе, в ней нет ничего особенного или экстраординарного, но...
Для календаря, который я делаю, мне понадобилось узнать, сколько недель затрагивает месяц. Решение пришло моментально:
Результат := Неделя_последнего_дня - Неделя_первого_дня;
В коде я оформил это так:
function GetWeekInMonth(ADate: TDate): Integer;
begin
Result := WeekOf(EndOftheMonth(ADate)) - WeekOf(StartOfTheMonth(ADate));
end;
Через полчаса понял, что решение не верное
.
