Ru-Board.club
← Вернуться в раздел «Прикладное программирование»

» Вопросы по Delphi (все версии) - часть 4

Автор: Yozj
Дата сообщения: 05.12.2008 19:12
samusev
Либо используй готовые библиотеки, либо напиши свой класс, скрывающий работу с юникодом.
Автор: RSoFT1978
Дата сообщения: 05.12.2008 20:30
samusev
Если это текстовый файл (.TXT), то кодировка значения не имеет. Объявляй файловую переменную F типа text, строку s и читай файл построчно
repeat
readln(F,s);
...
until eof(F);

Если нужно изменить кодировку, то используй функцию Utf8ToAnsi(s);
Автор: akaGM
Дата сообщения: 05.12.2008 21:13
только s как : WideString; т.к. string не во всех версиях двухбайтная дефолтом...
Автор: Yozj
Дата сообщения: 05.12.2008 21:34
akaGM
+1 Если это будет обычный string, то попавшийся символ нуля всё тебе испортит, а такой символ будет попадаться (в зависимости от текста) через раз.
Автор: DmitryKz
Дата сообщения: 05.12.2008 22:04
Ребята, посоветуйте софтину для подсчета строк написанного кода. В смысле, во всех pas-файлах проекта.

Добавлено:
И еще такой вопрос: можно ли как-то в программе определить версию, т.е. ту инфу, которая пишется в свойствах проекта: мажор, минор, релиз, билд?
Автор: V1s1ter
Дата сообщения: 05.12.2008 23:26
DmitryKz

Цитата:
И еще такой вопрос: можно ли как-то в программе определить версию, т.е. ту инфу, которая пишется в свойствах проекта: мажор, минор, релиз, билд?

function GetFileVersion(aFileName: String): String;
var
L, Linf: Cardinal;
S: PAnsiChar;
P, Pinf: Pointer;
V: String;
begin
S := PAnsiChar(aFileName);
L := GetFileVersionInfoSize(S, Linf);
GetMem(P, L);
if not GetFileVersionInfo(S, 0, L, P) then begin
L := GetLastError;
Result := '?';
end
else if not VerQueryValue(P, '\', Pinf, Linf) then begin
L := GetLastError;
Result := '?';
end
else begin
Result :=
IntToStr(HiWord(PVSFixedFileInfo(Pinf).dwFileVersionMS))+'.'+
IntToStr(LoWord(PVSFixedFileInfo(Pinf).dwFileVersionMS))+'.'+
IntToStr(HiWord(PVSFixedFileInfo(Pinf).dwFileVersionLS))+'.'+
IntToStr(LoWord(PVSFixedFileInfo(Pinf).dwFileVersionLS));
end;
FreeMem(P);
end;
Автор: Maks150988
Дата сообщения: 06.12.2008 00:06
ShIvADeSt
Спасибо, работает. А вы не подскажете способ как нормально закруглить окно кнопки? А то хоть и овнердрав, но она "остроугольная". Или может сабкласс статика на WM_MOUSEMOVE? Но он не работает...
Автор: ShIvADeSt
Дата сообщения: 06.12.2008 00:55
Maks150988

Цитата:
Спасибо, работает. А вы не подскажете способ как нормально закруглить окно кнопки? А то хоть и овнердрав, но она "остроугольная".

Что имеешь ввиду под закруглить. Или ты про поведение, что если нажать на кнопку за пределами рисунка но в границах реальной кнопки, то она все равно нажмется?
Автор: Maks150988
Дата сообщения: 06.12.2008 08:36
ShIvADeSt
Ну то есть имеется 32-битная картинка, где есть альфа канал еще, а может мы имеем такую же иконку. Рисунок на ней круглый, а все остальное прозрачно. Например можно создать ImageList из 4 картинок в одной для 4 состояний кнопки. А уже изображения для кнопки из него вытягивать через функцию ImageList_GetIcon и потом через DrawIconEx отображать. Проблема то в том что если уже натянут на диалог рисунок, а тут мы отображаем иконку из списка изображений - видно "квадрат" кнопки. Это ж получается само окно то кнопки не закруглено опять же. Хотел попробовать через овнердрав статика, но там не приходят ODS сообщения в дравитеме и через трекмаусевент тоже не получилось (а может я опять что-то напутал в спешке когджа код переделывал).
Мне видится такой вариант - просчитывать координаты на основном диалоге и через PtInRect проверять их и уже просто в WM_PAINT после накладывания основго рисунка для диалога выводить значок нужный через DrawIconEx. нО это конечно мудрено все, нет ли варианта попроще?


Сделал со стактиком такой код, проверил чтоб было ODT_STATIC в WM_DRAWITEM. Блин, такое ощущение что не изменяется толком сообщение ODT для контрола. Или этот ODS_SELECTED не работает в статике системном... И ведь пробовал еще сабклассингом делать булевую переменную подставлять и вслучае изменения подставлять в DrawIconEx нужный значок, но ничего не менялось, решил поэтому опробовать на DrawTextW. То же самое. Где ошибка, не подскажете?

[more=>>>]program skincore;

uses
Windows, Messages, CommCtrl;

const
szClassName = 'VanillaClass';
RC_BUTTON_PLAY = 102;

var
hApp : THandle;
szSkinPath : WideString;
hInstanceW : Thandle;
hImLst : HIMAGELIST;
hImBmp : HBITMAP;
MouseOver_ :hIcon;
PlayIsMouse:Boolean;
PlayBtnProc:Pointer;

procedure CenterWindow(hWindow: THandle);
var
WndRect : TRect;
iWidth : Integer;
iHeight : Integer;
begin
GetWindowRect(hWindow, WndRect);
iWidth := WndRect.Right - WndRect.Left;
iHeight := WndRect.Bottom - WndRect.Top;
WndRect.Left := (GetSystemMetrics(SM_CXSCREEN) - iWidth) div 2;
WndRect.Top := (GetSystemMetrics(SM_CYSCREEN) - iHeight) div 2;
MoveWindow(hWindow, WndRect.Left, WndRect.Top, iWidth, iHeight, FALSE);
end;

{}
procedure PaintImageFileButton(DC: HDC; Rect: TRect; szPathFile: WideString);
var
NewBmp: HBITMAP;
OldBmp: HBITMAP;
CompDC: HDC;
begin
CompDC := CreateCompatibleDC(0);
NewBmp := LoadImageW(0, PWideChar(szPathFile), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
OldBmp := SelectObject(CompDC, NewBmp);
BitBlt(DC, 0, 0, Rect.Right - Rect.Left, Rect.Bottom - Rect.Top, CompDC, 0, 0, SRCCOPY);
SelectObject(CompDC, OldBmp);
DeleteDC(CompDC);
DeleteObject(NewBmp);
end;

{}
procedure GetBitmapRect(szPathFile: WideString; var plRect: TRect);
var
Bitmap: HBITMAP;
bInfo : TBitmapInfo;
begin
Bitmap := LoadImageW(0, PWideChar(szPathFile), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
GetObject(Bitmap, SizeOf(bInfo), @bInfo);
plRect.Right := bInfo.bmiHeader.biWidth;
plRect.Bottom := bInfo.bmiHeader.biHeight;
DeleteObject(Bitmap);
end;

function DrawPlayButton(hWnd: HWND; uMsg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
var
lpPoint: TPoint;
lpRect : TRect;
begin
case uMsg of
WM_MOUSEMOVE:
begin
GetCursorPos(lpPoint);
GetWindowRect(hWnd, lpRect);
if PtInRect(lpRect, lpPoint) then
begin
if GetCapture <> hWnd then
begin
SetCapture(hWnd);
PlayIsMouse := TRUE;
end;
end
else
begin
ReleaseCapture;
PlayIsMouse := FALSE;
end;
InvalidateRect(hWnd, nil, FALSE);
end;
end;
Result := CallWindowProcW(PlayBtnProc, hWnd, uMsg, wParam, lParam);
end;

{}
function MainWndProc(hWnd: HWND; uMsg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
var
lpRect : TRect;
lpPaint: TPaintStruct;
lpdis : PDrawItemStruct;
begin
Result := 0;
case uMsg of
{}
WM_CREATE:
begin
hApp := hWnd;
{ устанавливаем путь к директории с файлами для оболочки }
szSkinPath := WideString(ExtractFilePathW(ParamStrW)) + 'images' + '\';

{ загружаем настройки оболочки для отображения картинок на окнах }
GetBitmapRect(WideString(szSkinPath + 'main_window_normal.bmp'), lpRect);
SetWindowLongW(hApp, GWL_EXSTYLE, GetWindowLong(hApp, GWL_EXSTYLE) or WS_EX_LAYERED);
SetLayeredWindowAttributes(hApp, RGB(255, 0, 255), (255 * 85) div 100, LWA_COLORKEY + LWA_ALPHA);
SetWindowPos(hApp, 0, 0, 0, lpRect.Right, lpRect.Bottom, SWP_NOZORDER);

{}
GetBitmapRect(WideString(szSkinPath + 'play_button_normal.bmp'), lpRect);
CreateWindowExW(0, 'STATIC', '', SS_OWNERDRAW or WS_CHILD or WS_VISIBLE or WS_TABSTOP, 85, 32, lpRect.Right, lpRect.Bottom, hApp, RC_BUTTON_PLAY, hInstanceW, nil);

{ создаем список с изображениями }
hImBmp := LoadImageW(0, PWideChar(WideString(ExtractFilePathW(ParamStrW)) + 'testbmp.bmp'), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
hImLst := ImageList_Create(lpRect.Right, lpRect.Bottom, ILC_COLOR32, 4, 0);
ImageList_Add(hImLst, hImBmp, hImBmp);
//ImageList_SetBkColor(hImLst, RGB(255, 0, 255));
//MouseOver := ImageList_GetIcon(hImLst, 1, ILD_NORMAL);

PlayBtnProc := Pointer(GetWindowLongW(GetDlgItem(hApp, RC_BUTTON_PLAY), GWL_WNDPROC));
SetWindowLongW(GetDlgItem(hApp, RC_BUTTON_PLAY), GWL_WNDPROC, LongInt(@DrawPlayButton));

{ создаем регионы для окон кнопок }
// BitmapToRegion(GetDlgItem(hApp, RC_BUTTON_PLAY), WideString(ExtractFilePathW(ParamStrW) + 'testbmp.bmp'), TRUE);
CenterWindow(hApp);
end;

{}
WM_PAINT:
begin
//
BeginPaint(hApp, lpPaint);
GetClientRect(hApp, lpRect);
PaintImageFileButton(lpPaint.hDC, lpRect, WideString(szSkinPath + 'main_window_normal.bmp'));
EndPaint(hApp, lpPaint);
//
// BeginPaint(GetDlgItem(hApp, RC_BUTTON_PLAY), lpPaint);
// GetClientRect(GetDlgItem(hApp, RC_BUTTON_PLAY), lpRect);

// if PlayIsMouse then
// begin
// DrawIconEx(lpPaint.hDC, lpRect.Left, lpRect.Top, PlayIsMouse, 46, 46, 0, 0, DI_NORMAL);
// DrawTextW(lpPaint.hDC, PWideChar(WideString('yes')), -1, lpRect, DT_LEFT or DT_WORDBREAK or DT_VCENTER);
// end
// else
// begin
// DrawIconEx(lpPaint.hDC, lpRect.Left, lpRect.Top, ImageList_GetIcon(hImLst, 0, ILD_NORMAL), 46, 46, 0, 0, DI_NORMAL);
// DrawTextW(lpPaint.hDC, PWideChar(WideString('not')), -1, lpRect, DT_LEFT or DT_WORDBREAK or DT_VCENTER);
// end;

// EndPaint(GetDlgItem(hApp, RC_BUTTON_PLAY), lpPaint);
//
//Result := 0;
end;

{}
WM_DRAWITEM:
begin
lpdis := PDrawItemStruct(lParam);
case lpdis.CtlType of
ODT_STATIC:
begin
case lpdis.CtlID of
RC_BUTTON_PLAY:
begin
if (lpdis.itemState and ODS_SELECTED) <> 0 then
DrawTextW(lpdis.hDC, PWideChar(WideString('press')), -1, lpdis.rcItem, DT_LEFT or DT_WORDBREAK or DT_VCENTER)
else
DrawTextW(lpdis.hDC, PWideChar(WideString('normal')), -1, lpdis.rcItem, DT_LEFT or DT_WORDBREAK or DT_VCENTER);
// if PlayIsMouse and not ((lpdis.itemState and ODS_SELECTED) <> 0) then
// DrawTextW(lpdis.hDC, PWideChar(WideString('hover')), -1, lpdis.rcItem, DT_LEFT or DT_WORDBREAK or DT_VCENTER);
// if (lpdis.itemState and ODS_DISABLED) <> 0 then
// DrawTextW(lpdis.hDC, PWideChar(WideString('disable')), -1, lpdis.rcItem, DT_LEFT or DT_WORDBREAK or DT_VCENTER);
end;
end;
end;
end;
end;
{}
WM_CLOSE, WM_DESTROY:
begin
DeleteObject(hImLst);
PostQuitMessage(0);
end;
{}
else
Result := DefWindowProc(hWnd, uMsg, wParam, lParam);
end;
end;

var
wCls: TWndClassExW;
uMsg: TMsg;
hDlg: Thandle;
begin
InitCommonControls;
hInstanceW := GetModuleHandleW(nil);

ZeroMemory(@wCls, SizeOf(wCls));
wCls.cbSize := SizeOf(TWndClassExW);
wCls.style := CS_HREDRAW or CS_VREDRAW;
wCls.lpfnWndProc := @MainWndProc;
wCls.cbClsExtra := 0;
wCls.cbWndExtra := 0;
wCls.hInstance := hInstanceW;
wCls.hIcon := 0;
wCls.hCursor := LoadImageW(0, PWideChar(IDC_ARROW), IMAGE_CURSOR, 16, 16, LR_LOADTRANSPARENT or LR_SHARED);
wCls.hbrBackground := COLOR_BTNFACE + 1;
wCls.lpszMenuName := nil;
wCls.lpszClassName := szClassName;
RegisterClassExW(wCls);

hDlg := CreateWindowExW(WS_EX_LAYERED or WS_EX_TOOLWINDOW or WS_EX_TOPMOST, PWideChar(WideString(szClassName)), PWideChar(WideString(szClassName)), WS_POPUP or WS_SYSMENU or WS_OVERLAPPED or WS_SYSMENU, Integer(CW_USEDEFAULT), Integer(CW_USEDEFAULT), 0, 0, 0, 0, hInstanceW, nil);
ShowWindow(hDlg, SW_SHOWNORMAL);
UpdateWindow(hDlg);

while GetMessageW(uMsg, 0, 0, 0) do
if not (IsDialogMessageW(hDlg, uMsg)) then
begin
TranslateMessage(uMsg);
DispatchMessageW(uMsg);
end;

UnRegisterClassW(wCls.lpszClassName, hInstanceW);
DestroyWindow(hDlg);
//ExitCode := uMsg.wParam;
end.[/more]
Автор: Yozj
Дата сообщения: 07.12.2008 11:30
DmitryKz

Цитата:
Ребята, посоветуйте софтину для подсчета строк написанного кода. В смысле, во всех pas-файлах проекта.

Сам напиши, алгоритм простой:
- обходишь всю директорию рекурсивно
- если файл PAS, то передаешь его в процедуру обработки
- cчитал файл в StringList
- просуммировал количество строк

Как только реализуешь - захочется больше, к примеру не учитывать пустые строки или комментарии, всё это будет несложно добавить.
Автор: VAbramyak
Дата сообщения: 07.12.2008 19:40
Здравствуйте! Нужна помощь!
Есть библиотека DLL написана на C++. В ней есть експортируемая функция
_RunSQLConsole(Con : TADOConnection; Str : pchar) : pchar; stdcall.
При вызове этой функции, откривается форма с редактором запроса, текст запроса передается через параметр str, и после закрития формы тест передается вызываемому приложению. Нужно эту функуию вызвать из приложения написанного на delphi 2009.
функцию прикрутил в своем приложении вот так:

function _RunSQLConsole(Con : TADOConnection; Str : pchar) : pchar; Stdcall; External 'SQLTOOLS.dll';


Текст, передаваемый функции имеет тип string и на выходе надо тоже получить string.Вызов:

procedure TForm1.Button6Click(Sender: TObject);
var return, input : pchar;
begin
input := Pchar(SynEdit1.Text);
return := _RunSQLConsole(DM.ADOConnection1,input);
SynEdit1.Text := string(return);
end;


Правильно не работает, при вызове в открывшемся редакторе отображается непонятно что, а при закрытии вываливается ошибка обращения к памяти.
Подскажите как правильно реализовать это дело. Спасибо.
Автор: Url
Дата сообщения: 07.12.2008 21:18
у меня вопрос - почему в turbo delphi (Borland® Delphi® for Microsoft® Windows)
при использовании "randomize", счетный цикл "for .. to .. do" считает в обратном порядке?
Автор: V1s1ter
Дата сообщения: 07.12.2008 22:21
Url
Попробывал, вот код:

procedure TForm1.FormCreate(Sender: TObject);
var
I: Integer;
begin
randomize;
for I := 0 to 10 do begin
Caption := Caption+' '+IntToStr(i);
end;
end;

Вот результат 'Form1 0 1 2 3 4 5 6 7 8 9 10'
как видно утверждение

Цитата:
счетный цикл "for .. to .. do" считает в обратном порядке

не подтвердилось...
Автор: Frodo_Torbins
Дата сообщения: 07.12.2008 23:00
VAbramyak

Цитата:
Con : TADOConnection
В таких случаях самый верный способ - использование рантайм пакетов. Но поскольку библиотека написана на билдере, получается очень нехорошая ситуация. Единственный выход - использовать менеджер памяти, который умеет работать с библиотеками. Идеальный вариант FastMM4. Но такой менеджер должен использоваться как в приложении, так и в библиотеке, причем одной версии.
Автор: delover
Дата сообщения: 08.12.2008 06:42
Maks150988
Сорри за офтоп, тема была старая, вопрос в этой ветке про выполнение батников после билда в Delphi5, D6, D7, D2005, D2006. Выкладывал линку, может там её что-то надо?
Автор: RomanTim
Дата сообщения: 08.12.2008 06:53
Url
V1s1ter
Если включена оптимизация и в цикле не используется переменная, по которой он организуется, то компилятор делает обратный цикл
Автор: Yozj
Дата сообщения: 08.12.2008 08:16
RomanTim
Если переменная не используется, то и значение её нас волновать не должно, т.к. порядок выполнения прямой или обратный при этом не важен.
Автор: RomanTim
Дата сообщения: 08.12.2008 09:12
Yozj
Да я и не говорю, что компилятор работает неправильно, просто поясняю, чтобы человек не пугался
Автор: anfilat
Дата сообщения: 08.12.2008 09:24
VAbramyak

Цитата:
Нужно эту функуию вызвать из приложения написанного на delphi 2009.

А ты учитываешь, что D2009 по умолчанию используется юникод? Что бы твой код рабтал надо в нем везде заменить pchar на pansichar, а string на ansistring
Автор: Yozj
Дата сообщения: 08.12.2008 09:33
RomanTim
Да, но особенность очень интересная, я не был в курсе, спасибо.
Автор: fcdobpiy
Дата сообщения: 08.12.2008 10:55
RomanTim
даже если переменная используется, то цикл бывает и обратным.
неоднократно убеждался в процессе отладки. не мог понять почему. но т.к. все работало - плюнул
Автор: Yozj
Дата сообщения: 08.12.2008 11:36
fcdobpiy
Проверил, действительно в обратную сторону. Но оно понятно почему Delphi так оптимизирует, т.к. индекс не используется.
Если счетчик используется, то индексу присваивается значение первого элемента, а далее используется команда CMP для сравнения с последним значением индекса.
Если счетчик не используется, то индексу присваивается значение количества циклов, а далее используется команда DEC, для уменьшения индекса до нуля.
CMP - 3 байта, 15 тактов
DEC - 1 байт, 3 такта
оптимизация на лицо
Это всё действует, если границы заданы константами, иначе с вариациями.
Автор: Url
Дата сообщения: 08.12.2008 11:37
fcdobpiy
вот и я про то

Добавлено:
Yozj а как отключить оптимизацию? и что плохого можно ждать при ее отключении?
Автор: Yozj
Дата сообщения: 08.12.2008 11:53
Url
Project -> Options (Shift+Ctrl+F11) -> закладка Compile, галочка Otimization
Сравнив сгенерированный код с оптимизацией и без нее - так и хочется ее включить, т.к. количество используемых командами байт и тактов сильно превышает оптимизированный вариант. Но, мне кажется, это по большому счету мало влияет на скорость исполнения программы, так что если есть глюки из-за оптимизации - лучше ее отключить.
Автор: Artem59
Дата сообщения: 08.12.2008 12:55
Вопрос следующего порядка.
Немного отошел от Делфи. Работал последний раз 4 года назад. Сейчас больше 1С. Надо сделать один проект на Делфи. Программа должна формировать очень сложные выходные формы (полиса по страхованию) в виде таблиц. Раньше я пользовался QuickReport (в 6-ой версии Delphy). Но он был не приспособлен для сложных форм. Сейчас какие веяния в этом вопросе? Есть что-то стандартное с хорошими возможностями? Покупать что-то внешнее для одного раза не хочется.
Автор: delover
Дата сообщения: 08.12.2008 14:09
Maks150988
Да забыл, там работает автоматическая дата сохранения, т.е. в хидер падает прямо в редактор дата сохранённого файла, на счёт D2009 не знаю, похоже что и там должно работать, так как вроде всё компилится ОК.
Автор: VAbramyak
Дата сообщения: 08.12.2008 14:30
anfilat
Все заработало после замены pchar на pansichar. Cпасибо за совет.
Автор: Maks150988
Дата сообщения: 08.12.2008 20:03
delover
Я немного подзабыл уже. Киньте ссылку. Я работаю в Делфи 7.

Так, а у меня вопросик. Вот решил ради интереса сделать проект, чтобы сразу использовать только нужные функции и размер был максимально минимально-возможным. http://webdrive.avtograd.ru/Download/Explorer/sources/Project1.zip Правда программа не запускается. Что-то фиг знает что надо, вроде все правильно, с мессаджбоксом же работает способ, а диалогбокс не прокатывает...

И еще аналог блиттингбаттон на чистом апи. Посмотрел в сторону прорисовки кнопок через отрисовку элементов системных тем. Пришлось выкинуть много мусора из кода и оставить используемые функции и переменные. http://webdrive.avtograd.ru/Download/Explorer/sources/button_theme_src.zip Есть вопрос по поводу критических секций - нужно ли в финализации делать их удаление? И достаточно ли в момем случае LeaveCriticalSection?
Автор: delover
Дата сообщения: 09.12.2008 06:54
Maks150988
У меня D2006 (на этом компе Turbo Delphi, т.е. без компилятора командной строки) и она не компилит

Код: [no][Pascal Fatal Error][/no] Project1.dpr(1): F2063 Could not compile used unit 'SysInit.pas'
Автор: delover
Дата сообщения: 09.12.2008 10:35
Maks150988
В тулзе приходится подменять сервис модулей, чтоб с каждым открытым файлом в иде-хе существовал объект, но я уже писал про это. Так дата падает в редактор до непосредственно сохранения (округляется в формат FAT + 2 секунды). Обычно попадает, но раз в месяц в окно сообщений build пишет, если ошиблась с секундами. Так что уже сохранённый файл остаётся немодифицированным и идентичным хранящемуся на диске.

Страницы: 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667

Предыдущая тема: Глобальные переменные в разных формах с++ builder 'a.


Форум Ru-Board.club — поднят 15-09-2016 числа. Цель - сохранить наследие старого Ru-Board, истории становления российского интернета. Сделано для людей.