-
Новости от 27 марта 2010 (KOL & MCK v2.90)
[-]
Для символа USE_NAMES, исправлен SetName
Hallif, VK
[*]
TStrList, TStrListEx (так же частично для TWStrList, TWStrListEx) методы IndexOf, IndexOf_NoCase, Find и Sort улучшены, добавлен FindFirst
VK, mdw
[-]
Восстановлена совместимость с Delphi2 и Delphi3
VK
[*]
UNI
Дополнительные изменения для улучшения UNICODE_CTRLS: RemoveSpaces, AnsiCompareText, AnsiCompareStrA, _AnsiCompareStrA, AnsiCompareStrNoCaseA, _AnsiCompareStrNoCaseA, AnsiEq, CompareLVColumns
[-]
Ссылка на uxtheme изменена на uxtheme.dll.
MTsv DN
[-]
Исправления в декларациях (для определенного символа STREAM_COMPAT): SeekMemStream, SetSizeMemStream, ReadMemStream, WriteMemStream, WriteExMemoryStream.
Hallif
[-]
Исправление в WndProcToolbarCtrl для Win98
MTsv DN
[+]
TIcon.LoadFromXXXX теперь понимает иконки WinCE (16 бит на пиксель)
mdw
[+]
ASM версия для WinVer
MTsv DN, VK
[*]
MCK
В mirror.pas и mckCtrls.pas, введен тип TDelphiString и все условные декларации по устранены - для правильной работы Code Completion.
VK
[-]
TAction.LinkMenuItem исправлен для динамических меню
mdw
[*]
В WndProc_LVCustomDraw, Canvas больше не создается.
mdw
-
Не понимаю, почему так уопрно не хотите юзать свн... но все же обновил его. Теперь есть пара отличий: - delphidef.inc удален, вся информация перенесена в KOLDEF.inc * про MCKAppExpert200x, MTsvDN уже писал, но напомню:
procedure TMCKWizard.Execute;
var
prj: String;
unt: String;
dlg: TSaveDialog;
lst: TStringList;
begin
dlg := TSaveDialog.Create(nil);
dlg.Options := [ofOverwritePrompt, ofExtensionDifferent, ofPathMustExist];
dlg.Title := 'Save Project';
dlg.Filter := 'DPR files|*.dpr';
dlg.DefaultExt := 'dpr';
if dlg.Execute then begin
prj := dlg.FileName;
if (Pos('.', prj) = Length(prj) - 3) then
SetLength(prj, Length(prj) - 4);
dlg.Title := 'Save Unit';
dlg.Filter := 'PAS files|*.pas';
.....
KOL.pas: * шрифт по умолчанию Tahoma, размер шрифта -11 + добавлена функция Swap для Byte
procedure Swap( var X, Y: Integer ); overload;
var Tmp: Integer;
begin
Tmp := X;
X := Y;
Y := Tmp;
end;
asm
MOV ECX, [EDX]
XCHG ECX, [EAX]
MOV [EDX], ECX
end;
procedure Swap(var X, Y: Byte); overload;
var
T: Byte;
begin
T := X;
X := Y;
Y := T;
end; + добавлена функции _GetDIBPixelsTrueColorWithAlpha, _SetDIBPixelsTrueColorWithAlpha (для 32битных битмапов, старый код вырезает альфу) function _GetDIBPixelsTrueColorWithAlpha( Bmp: PBitmap; X, Y: Integer ): TColor;
var
Pixel: DWORD;
RGB: TRGBQuad;
begin
Pixel := PDWORD( Integer(Bmp.fScanLine0) + Y * Bmp.fScanLineDelta +
X * Bmp.fBytesPerPixel )^ and $FFFFFFFF;
RGB := TRGBQuad(Pixel);
Swap(RGB.rgbBlue, RGB.rgbRed);
Result := TColor( RGB );
end;
function TBitmap.GetDIBPixels(X, Y: Integer): TColor;
begin
if not Assigned( fGetDIBPixels ) then
begin
if fHandleType = bmDIB then
begin
fScanLine0 := ScanLine[ 0 ];
fScanLineDelta := Integer(ScanLine[ 1 ]) - Integer(fScanLine0);
case PixelFormat of
pf1bit:
begin
fPixelMask := $01;
fPixelsPerByteMask := 7;
fGetDIBPixels := _GetDIBPixelsPalIdx;
end;
pf4bit:
begin
fPixelMask := $0F;
fPixelsPerByteMask := 1;
fGetDIBPixels := _GetDIBPixelsPalIdx;
end;
pf8bit:
begin
fPixelMask := $FF;
fPixelsPerByteMask := 0;
fGetDIBPixels := _GetDIBPixelsPalIdx;
end;
pf15bit:
begin
fPixelMask := 15;
fGetDIBPixels := _GetDIBPixels16bit;
end;
pf16bit:
begin
fPixelMask := 16;
fGetDIBPixels := _GetDIBPixels16bit;
end;
pf24bit:
begin
fPixelsPerByteMask := 0;
fBytesPerPixel := 3;
fGetDIBPixels := _GetDIBPixelsTrueColor;
end;
pf32bit:
begin
fPixelsPerByteMask := 1;
fBytesPerPixel := 4;
fGetDIBPixels := _GetDIBPixelsTrueColorWithAlpha_GetDIBPixelsTrueColor;
end;
else;
end;
end;
if not Assigned( fGetDIBPixels ) then
begin
Result := Pixels[ X, Y ];
Exit;
end;
end;
Result := fGetDIBPixels( @Self, X, Y );
end;
...
procedure _SetDIBPixelsTrueColorWithAlpha(Bmp: PBitmap; X, Y: Integer; Value: TColor);
var RGB: TRGBQuad;
Pos: PDWord;
begin
RGB := TRGBQuad((Value));
Swap(RGB.rgbBlue, RGB.rgbRed);
Pos := PDWORD( Integer(Bmp.fScanLine0) + Y * Bmp.fScanLineDelta
+ X * Bmp.fBytesPerPixel );
Pos^ := Pos^ or DWORD(RGB);
end;
procedure TBitmap.SetDIBPixels(X, Y: Integer; const Value: TColor);
begin
if not Assigned( fSetDIBPixels ) then
begin
if fHandleType = bmDIB then
begin
fScanLine0 := ScanLine[ 0 ];
fScanLineDelta := Integer(ScanLine[ 1 ]) - Integer(fScanLine0);
case PixelFormat of
pf1bit:
begin
fSetDIBPixels := _SetDIBPixels1bit;
end;
pf4bit:
begin
fPixelMask := $0F;
fPixelsPerByteMask := 1;
fSetDIBPixels := _SetDIBPixelsPalIdx;
end;
pf8bit:
begin
fPixelMask := $FF;
fPixelsPerByteMask := 0;
fSetDIBPixels := _SetDIBPixelsPalIdx;
end;
pf15bit:
begin
fPixelMask := 15;
fSetDIBPixels := _SetDIBPixels16bit;
end;
pf16bit:
begin
fPixelMask := 16;
fSetDIBPixels := _SetDIBPixels16bit;
end;
pf24bit:
begin
fPixelsPerByteMask := 0;
fBytesPerPixel := 3;
fSetDIBPixels := _SetDIBPixelsTrueColor;
end;
pf32bit:
begin
fPixelsPerByteMask := 1;
fBytesPerPixel := 4;
fSetDIBPixels := _SetDIBPixelsTrueColorWithAlpha_SetDIBPixelsTrueColor;
end;
else;
end;
end;
if not Assigned( fSetDIBPixels ) then
begin
Pixels[ X, Y ] := Value;
Exit;
end;
end;
fSetDIBPixels( @Self, X, Y, Value );
end;
KOLasm.inc: * изменен на использование _GetDIBPixelsTrueColorWithAlpha, _SetDIBPixelsTrueColorWithAlpha
-
delphidef.inc удален, вся информация перенесена в KOLDEF.incДавно это произошло? Верните на место. Я сейчас попробую объяснить. koldef.inc предназначен для включения в любой файл проекта, не только в KOL.pas. Его задача - помочь бороться с тысячами ненужных предупреждений от компиляторов новых версий, в основном, ну и уже заодно - добавить символы условной компиляции _$Dxx, _$DxxorHigher и т.п., чтобы можно было в проектах тоже учитывать версию компилятора. delphidef.inc содержит определения только для kol.pas. MCKAppExpert200x - к этому продукту я отношения не имею. Если надо, могу поменять ссылку на странице загрузок на то место, где есть актуальный архив. шрифт по умолчанию Tahoma, размер шрифта -11 Сколько раз уже писал, что не надо так делать. Дефолтный фонт должен быть таким, чтобы не приходилось его устанавливать программным кодом, пусть даже его генерит автоматом MCK. Кому надо установить в MCK желаемый дефолтный фонт на проект - TKOLProject.DefaultFont + TKOLForm.fontDefault = true. По умолчанию вообще должен быть фонт System, это где-то это когда-то вызывало неприятности, уже не помню где. Против Tahoma я как бы не возражаю как против дефолтного не системного, но он появился как обязательный только начиная с win98, если не ошибаюсь. Нет, не ошибаюсь: http://itua.info/news/hardware/3726.htmlА мы вроде как и Win95 поддерживаем. procedure Swap( var X, Y: Integer ); overload; Не очень хорошо. Для Delphi2, 3, и кажется 4, overload - слово неизвестное. Уже лучше назовите SwapBytes. (Можно и IFDEF'ами, но тогда пользователи старых Delphi лишаются одной функции, и непонятно зачем). добавлена функции _GetDIBPixelsTrueColorWithAlpha, _SetDIBPixelsTrueColorWithAlpha (для 32битных битмапов, старый код вырезает альфу Не проще ли было поправить (по кондиции или сразу) Color2RGBQuad, ведь альфа именно там и отрезается в _Set, а для _Get - изменить саму _GetDIBPixelsTrueColor (там Color2RGBQuad всего лишь для обмена R и B, и вызывается просто по принципу "вылить из чайника и вызвать уже готовый код"). SVN я не пробовал, пока на диал-апе сидел. Когда платишь за каждую лишнюю минуту онлайна, сидеть и разбираться, что к чему, некогда. Сейчас можно. Хотя новшеств я не люблю. Если они не позволяют радикально облегчить жизнь. Потому и Delphi 20хx не люблю.
-
delphidef- только для КОЛа, а KOLDEF для всего... малость не понятно %) плюс к этому внутри delphidef.inc можно обнаружить {$I KOLDEF.INC}... MCKAppExpert200x- находится в вашем архиве, поэтому и стоит его исправить Насчет поддержки 95... Просто каждый раз начиная новый проект (в котором хотелось бы иметь "обычный виндовый шрифт"), с установленным, по умолчанию System приходится его каждый раз менять.. А так один раз поставил и забыл.. Вылез в 95ой глюк - исправил.. Swap Это еще повезло, что inline; не успел воткнуть :D Конечно можно и переименовать, но имхо лучше в сторону юзабельности отказываться от старых версий.. D2 оно зачем ваще? GetDIBPixelsTrueColorWithAlpha, SetDIBPixelsTrueColorWithAlpha А вот тут как раз, чтоб не испортить старое, добавил совершенно отдельными функциями SVN Предлагаю разобраться как время будет =) я сделаю доступ Вам и сможете напрямую все обновлять. Минусов в SVN нет имхо, даже тот кто не хочет качать через svn-клиент, может сливать все через браузер (GNU tarball) Delphi 20хx На самом деле привыкнуть гораздо быстрее чем кажется. Ну и от задач все зависит. Сейчас сижу на Турбе, а уже хотелось бы генереки... USE_CONSTRUCTORS, KOLCLASSES USE_CONSTRUCTORS - давно не работает. По KOLCLASSES уже давно не хватает кода.. Реально ли восстановить функциональность? И какой будет прирост к размеру ЕХЕ, если использвать class вместо object? Напоминаю адрес SVN http://sourceforge.net/projects/kolmck/
-
Ну как же не понятно. Посмотрите, что в них есть. Я всегда включаю koldef.inc во все исходные файлы, чтобы получить удаление всех предупреждений, не имеющих смысла для низкоуровневого кода. И получить символы версии в нормальных запоминаемых буквах, тем более кумулятивные символы сам Delphi Не дает, если ver120, то она и есть 120, а 130 отдельно сравнивать надо. И зачем мне надо, чтобы в каждом исходном файле вставлялись символы из delphidef.inc.
MCKAppExpert200x - перенаправил ссылку на kolnmck.
Вылез в 95ой глюк - исправил. Я вот не могу даже запустить под 95, у меня ее нет. Глюк вылезет у того, кто запустит готовую программу на 95.
имхо лучше в сторону юзабельности отказываться от старых версий.. D2 оно зачем ваще?Delphi2 поддерживает coff-формат объектных файлов, это единственная версия Delphi, в которой можно делать драйвера. А зачем мне Delphi 5 ? Да потому что он не тормозит даже по сравнению с Delphi 7. И нет никаких особых преимуществ у новых версий по сравнению со старыми. Delphi 20хx На самом деле привыкнуть Поэтому дело не в том чтобы привыкнуть, а в тормозах. А привыкать чего, я же на шарпе работал, тот же дико неудобный интерфейс. Но главное - тормоза.
До сих пор в KOL не было почти ни одного overload'а. Зачем их добавлять, тем более из-за такой функции, для которой отдельное имя никак не уменьшит юзабельности. Я же так понял, что он только для обмена каналов R и B в цвете используется. Пока не поздно, надо поменять.
GetDIBPixelsTrueColorWithAlpha, SetDIBPixelsTrueColorWithAlpha А вот тут как раз, чтоб не испортить старое Зачем портить IFDEF, никто не отменял.
USE_CONSTRUCTORS, KOLCLASSES USE_CONSTRUCTORS - давно не работает. Но и выбрасывать тоже как-то не вижу особой причины. По KOLCLASSES уже давно не хватает кода. Это хуже, но тоже поправимо. На все надо время. Прирост небольшой, ровно как после включения classes, килобайт 30.
-
Не могу SVN запустить. Я Explorer'ом обычно не пользуюсь. А тут запустил для svn - и сразу после этого и-нет стал недоступен. Отключил Web-экран в авасте, этот сайт пошел, теперь kolmck.net и Soundforge недоступен. Вроде пингуются. Ерунда какая-то. В общем, сегодня и-нет барахлит, не получится.
-
Господа, всплыл неприятный глюк. Метод TMenu.RemoveSubMenu в версиях 2.89 и 2.90 оставляет утечку памяти (по fastmm4). В версии 2.88 такого не было, проверил. Если закомментировать строку M.FMenuItems.Remove( Result ); в методе TMenu.RemoveSubMenu, то фастмм доволен, но и Count не уменьшается
-
А если заменить M.FMenuItems.Remove( Result ); на if Result.FParentMenu <> nil then
Result.FParentMenu.FMenuItems.Remove( Result ); ?
-
Второй вариант - на Items.Remove(Result); уже без всяких условий.
-
Items.Remove(Result); хочет, чтобы ему казали индекс, так как property Items[ Id: HMenu ]: PMenu . Первый вариант тоже не подходит, фастмм ругается на все то же
-
> TStrList, TStrListEx (так же частично для TWStrList, TWStrListEx) > методы IndexOf, IndexOf_NoCase, Find и Sort улучшены...
Владимир, нашел ошибку в Find(). Возникает, если искомая строка больше любой строки в списке. Вот простейший пример:
var SL: PStrList; I: Integer; begin SL:= NewStrList; SL.Add('0'); SL.Add('1'); SL.Add('2'); SL.Add('3'); SL.Sort(False); SL.Find('1', I); //Здесь отрабатывает нормально SL.Find('2', I); //Здесь отрабатывает нормально SL.Find('4, I); //Здесь валится SL.Free;
Посмотрел код, причина - выхода индекса за пределы диапазона в последнем сравнивании метода Find(). Если использовать AnsiSort, по AV не возникает, но только потому, что используются другие функции сравнивания.
-
Так поправил: .... if (L < FCount) and not Result then Result := fCompareStrListFun( PAnsiChar( fList.Items[ L ] ), PAnsiChar( S ) ) = 0; end;
-
Вытащил версию. Было так (в 2.88): function TMenu.RemoveSubMenu( ItemToRemove: Integer ): PMenu;
var OK: Boolean;
begin
Result := Items[ ItemToRemove ];
if Result = nil then Exit;
if Result.FParentMenu <> nil then
OK :=
RemoveMenu( Result.FParentMenu.FHandle, Result.FId, MF_BYCOMMAND )
else
OK :=
RemoveMenu( FHandle, Result.FId, MF_BYCOMMAND );
if not OK then
ShowMessage( 'Error removing menu: ' + Int2Str( GetLastError ) + ' - ' +
SysErrorMessage( GetLastError ) );
if Count = 0 then
begin
Result.Free;
Result := nil;
end;
RedrawFormMenuBar;
end;
Стало так (в 2.89-2.90): function TMenu.RemoveSubMenu( ItemToRemove: Integer ): PMenu;
var OK: Boolean;
var M: PMenu;
begin
Result := Items[ ItemToRemove ];
if Result = nil then Exit;
M := Result.FParentMenu;
if M = nil then M := @Self;
OK :=
RemoveMenu( M.FHandle, Result.FId, MF_BYCOMMAND );
M.FMenuItems.Remove( Result );
if not OK then
ShowMessage( 'Error removing menu: ' + Int2Str( GetLastError ) + ' - ' +
SysErrorMessage( GetLastError ) );
if Count = 0 then
begin
Result.Free;
Result := nil;
end;
RedrawFormMenuBar;
end;
Хоть тресни, никак не могу углядеть разницы, кроме формально другого кода с использованием промежуточной переменной. И добавления M.FMenuItems.Remove( Result ); Наконец, просто попробуйте вернуть старый код из 2.88. Если там шло и без утечек. И тогда надо разобраться зачем я добавил (по чьей просьбе) эту строчку. У меня почему-то не помечено, кто просил. Ага, MTsv DN: http://pda.delphimaster.net/?id=1259909126&n=10Чтобы Count уменьшался типа.
-
2mdw: if (L < FCount) and not Result then
Допускаю. На тестах ищется только случайная строка из самого списка. Но, кажется, так будет лучше:
...
if L >= Count then
Dec( L );
Index := L;
if not Result then
Result := fCompareStrListFun( PAnsiChar( fList.Items[ L ] ),
PAnsiChar( S ) ) = 0;
Через параметр Index возвращается в любом случае последняя строка как ближайшая найденная, возвращаемый результат FALSE. Или неважно, лишь бы не падало в случае если больше чем любая в списке?
-
Чего-то у меня черепашка svn не может достучаться до nekki.ru. Пишет Cannt connect to host. A connection attempt failed because the connection party did not properly respond after a period of time or established connection failed because connected host has failed to respond. В файрволле крыжык на TortoiseProc.exe стоит. Web-экран в avast! отключен. Не знаю, чего ему еще надо. Может мой провайдер отсекает. ping идет, http://nekki.ru работает.
-
> Через параметр Index возвращается в любом случае последняя > строка как ближайшая найденная, возвращаемый результат FALSE. > Или неважно, лишь бы не падало в случае если больше чем > любая в списке?
Да мне в конкретном случае пофиг, главное - найдено\не найдено. Поэтому так и поправил. Но возможно, кому-то действительно будет важно еще и ближайшая "найденая" строка, да и описанию функции будет соответствовать. :) Ваш вариант оставляем тогда.
-
> > Через параметр Index возвращается в любом случае последняя > > строка как ближайшая найденная, возвращаемый результат > FALSE.> Или неважно, лишь бы не падало в случае если больше > чем > любая в списке?Да мне в конкретном случае пофиг, главное > - найдено\не найдено. Поэтому так и поправил. Но возможно, > кому-то действительно будет важно еще и ближайшая "найденая" > строка, да и описанию функции будет соответствовать. :) > Ваш вариант оставляем тогда.
Хотя, другой стороны, то Index = FCount информирует о том, что строка именно больше последней... В общем, не знаю, на Ваше усмотрение, как правильнее...
-
Я предпочел Count-1, т.к. планировал Find использовать для вставки в уже отсортированный список новых строк так, чтобы список оставался отсортированным. Если возвращается false, сравниваем со строкой по индексу, если получилась новая больше, делаем Insert( Index+1, newS ), иначе Insert( Index, newS ). Оно и в случае Index==Count не страшно, но нужна еще одна дополнительная проверка, не вышел ли Index>=Count, зато строку в этом случае сравнивать не нужно. Можно и описание чуть-чуть поменять. Главное здесь - что быстрее. Но если смотреть, что быстрее, то еще быстрее не делать последнее сравнение, оно явно лишнее. А лучше вообще вот так: function TStrList.Find(const S: AnsiString; var Index: Integer): Boolean;
var
L, H, I, C: Integer;
begin
Result := FALSE;
L := 0;
H := FCount - 1;
if H < 0 then Exit; if fAnsiSort then
begin
if fCaseSensitiveSort then
fCompareStrListFun := CompareAnsiCase
else
fCompareStrListFun := CompareAnsiNoCase;
end
else
begin
if fCaseSensitiveSort then
fCompareStrListFun := StrComp
else
fCompareStrListFun := StrComp_NoCase;
end;
C := 0;
while L <= H do
begin
I := (L + H) shr 1;
C := fCompareStrListFun( PAnsiChar( fList.Items[ I ] ),
PAnsiChar( S ) );
if C < 0 then L := I + 1 else
begin
H := I - 1;
if C = 0 then
begin
Result := TRUE;
Index := I;
Exit;
end;
end;
end;
Index := L;
if C < 0 then Index := -L;
end;
Т.е. возвращать в случае FALSE в Index индекс ближайшей строки, но если искомая меньше этой строки, то возвращать Index с минусом. Тогда проверка еще больше упрощается: if Index < 0 then Insert( -Index, sNew ) else Insert( Index+1, sNew ); И соответственно поправить описание.
-
Нет, немного не так. На тестах погонял, понял, что не то. Вот так лучше: function TStrList.Find(const S: AnsiString; var Index: Integer): Boolean;
var
L, H, C: Integer;
begin
Result := FALSE;
Index := 0;
L := 0;
H := FCount - 1;
if H < 0 then Exit; if fAnsiSort then
begin
if fCaseSensitiveSort then
fCompareStrListFun := CompareAnsiCase
else
fCompareStrListFun := CompareAnsiNoCase;
end
else
begin
if fCaseSensitiveSort then
fCompareStrListFun := StrComp
else
fCompareStrListFun := StrComp_NoCase;
end;
C := 0;
while L <= H do
begin
Index := (L + H) shr 1;
C := fCompareStrListFun( PAnsiChar( fList.Items[ Index ] ),
PAnsiChar( S ) );
if C < 0 then L := Index + 1 else
begin
H := Index - 1;
if C = 0 then
begin
Result := TRUE;
Exit;
end;
end;
end;
if C < 0 then Index := -L;
end;
-
А если немного улучшить StrComp, StrCom_NoCase, то еще быстрее. Где-то на 5%: function StrComp(const Str1, Str2: PAnsiChar): Integer; assembler;
asm
MOV EAX, [Str1]
MOV EDX, [Str2]
MOV CL, [EAX]
SUB CL, [EDX]
JZ @@compare
MOVSX EAX, CL
JMP @@fin
@@compare:
PUSH EDI
PUSH ESI
MOV EDI,EDX
XCHG ESI,EAX
OR ECX, -1
XOR EAX,EAX
REPE CMPSB
MOV AL,[ESI-1]
MOV DL,[EDI-1]
SUB EAX,EDX
POP ESI
POP EDI
@@fin:
end [ 'EAX', 'EDX', 'ECX' ] ;
function StrComp_NoCase(const Str1, Str2: PAnsiChar): Integer;
asm
MOV EAX, [Str1]
MOV EDX, [Str2]
PUSH EDI
PUSH ESI
MOV EDI,EDX
XCHG ESI,EAX
OR ECX, -1
MOV EDI,EDX
@@0:
XOR EDX,EDX
REPE CMPSB
MOV AL,[ESI-1]
MOV AH, AL
SUB AH, 'a'
CMP AH, 25
JA @@1
SUB AL, $20
@@1:
MOV DL,[EDI-1]
MOV AH, DL
SUB AH, 'a'
CMP AH, 25
JA @@2
SUB DL, $20
@@2:
MOV AH, 0
SUB EAX,EDX
JNZ @@exit
CMP DL, 0
JNZ @@0
@@exit:
POP ESI
POP EDI
end [ 'EAX', 'EDX', 'ECX' ] ;
|