Господа, у меня есть вопрос... Даже два. =(
Первый:
При написании VCL компонента столкнулся со странным поведением функции CreateDIBitmap — в некоторых случаях, возвращаемый хендл битмапа = 0, т.е. он попросту не создается...
Поясняю, компонент — эмулятор графического LCD дисплея. Его изображение хранится во внутреннем поле TBitmap и рисуется на канве компонента в методе Paint функцией Сanvas.StretchDraw(...) (компонент унаследован от TCustomControl)... Символы генерируются из массивов пикселов при разборе строки... Хранятся они вот так:
BigLetters : array['А'..'Я'] of TLetterPlace =
(
((1,1,1,1,1,1,1,1),//строки выровнены все норм..
(1,0,1,1,1,0,1,1),
(1,0,1,1,1,0,1,1),
(1,0,0,0,0,0,1,1),
(1,0,1,1,1,0,1,1),
(1,0,1,1,1,0,1,1),
(1,1,0,1,0,1,1,1),
(1,1,1,0,1,1,1,1))
,...............
Вот код метода компонента, который создает двухцветную картинку(символ) из массива значений пикселов:
procedure TbbLCD.MakeBMP(aSimb: PAnsiChar; IsScreen : Boolean; aInx : Integer; aBMP : TBitmap);//: TBitmap;
var
lpbInit : PAnsiChar;
pbi : PBitmapInfo;
i : Integer;
hBMP : HBITMAP;
begin
GetMem(pbi, SizeOf(TBitmapInfo) + 2*Sizeof(TRGBQUAD));
ZeroMemory(pbi, SizeOf(TBitmapInfo) + 2*Sizeof(TRGBQUAD));
pbi^.bmiHeader.biSize := SizeOf(TBitmapInfoHeader);
//блаблабла
for i := 0 to 1 do begin
pbi^.bmiColors[i].rgbBlue := i*180;
pbi^.bmiColors[i].rgbGreen := i*180;
pbi^.bmiColors[i].rgbRed := i*180;
end;
//блаблабла
try
hBMP := CreateDIBitmap(Canvas.Handle, pbi^.bmiHeader, CBM_INIT,
lpbInit, pbi^, DIB_RGB_COLORS);//<---------Вот здесь по непонятным мне причинам я получаю 0 if hBMP <> INVALID_HANDLE_VALUE then begin
aBMP.Handle := hBMP;
end;
finally
//блаблабла
end;
end;
hBMP=0 я получаю в случаях, когда изменяю заданные по умолчанию значения количества строк, числа символов в строке, масштаба и т.д. По умолчанию у эмулятора 4 строки и 16 символов в строке. При изменении последних и появляются эти так сказать "артефакты", то есть некоторые символы-битмапы не создаются.. Какой-то закономерности или системы в этом я не обнаружил. =\
эти символы накладываются на основной битмап-экран (код метода разбора строки):
procedure TbbLCD.ParseLine(aIndex: Integer; const aLine: String; aCurPos1 : Integer = -1; aCurPos2 : Integer = -1);
var
i, Bound : Integer;
tmp, tmpSpace : TBitMap;
Cursor{, PrevCursor} : Boolean;
pLine : PChar;
begin
pLine := PAnsiChar(aLine);
//блаблабла
tmpSpace := TBitmap.Create;
MakeBMP(@Simbols[' '], False, aIndex, tmpSpace);
if not Assigned(tmpSpace) then
Raise Exception.Create('Can not create Bitmap!');
try
while (i < Bound) do begin
tmp := TBitmap.Create;
if (Length(pLine) < Pred(Bound)) and (i > Pred(Length(pLine))) then
MakeBMP(@Simbols[' '], False, aIndex, tmp)
else case pLine[i] of
'А'..'Я':
MakeBMP(@BigLetters[pLine[i]], False, aIndex, tmp);
///
end;
if Cursor then
FScreen.Canvas.CopyMode := cmSrcInvert
else
FScreen.Canvas.CopyMode := cmSrcAnd;
if (FScreenState <> ss1lines) and (aIndex = 0) then
//
else
FScreen.Canvas.CopyRect(Rect(i*SimbW,(aIndex+Ord(FScreenState))*SimbH,
(i+1)*SimbW,(aIndex+1+Ord(FScreenState))*SimbH),
tmp.Canvas, Rect(0, 0, tmp.Width, tmp.Height));
Inc(i);
tmp.Free;
end;
finally
tmpSpace.Free;
end;
Refresh;
end;
В чем тут может быть дело??? Я что не освобождаю ресурсы API? Вариант попиксельно созданному битмапу присваивать значения из хранимых матриц реализовать было лень (хотя это наверное и проще зато медленнее). Кстати эти матрицы хранятся в отдельном модуле. Может быть их можно хранить как-то компактнее без потери скорости доступа??
А теперь вопрос второй, если вы еще не очень от меня устали 8) ....
После создания из данного компонента ActiveX Control и регистрации в Дельфи он просто напросто отрисовывает свою рамку и больше ничего не отрисовывает , даже при условиях, когда VCL компонент работает отлично (без так сказать "артефактов")!!! Вай?....
Заранее спасибо тем кто откликнется!
Надеюсь я был не слишком назойлив...
З.Ы. D6, Win2000 & XP
Здравствуйте, siniypin, Вы писали:
S>Господа, у меня есть вопрос... Даже два. =(
S>Первый:
S>При написании VCL компонента столкнулся со странным поведением функции CreateDIBitmap — в некоторых случаях, возвращаемый хендл битмапа BigLetters : array['А'..'Я'] of TLetterPlace =
(
((1,1,1,1,1,1,1,1),//строки выровнены все норм..
(1,0,1,1,1,0,1,1),
,...............
Каждую такую строчку можно было как в старые добрые времена сделать одним байтом.
S>Вот код метода компонента, который создает двухцветную картинку(символ) из массива значений пикселов:
procedure TbbLCD.MakeBMP(aSimb: PAnsiChar; IsScreen : Boolean; aInx : Integer; aBMP : TBitmap);//: TBitmap;
end;
S>В чем тут может быть дело??? Я что не освобождаю ресурсы API? Вариант попиксельно созданному битмапу присваивать значения из хранимых матриц реализовать было лень (хотя это наверное и проще зато медленнее). Кстати эти матрицы хранятся в отдельном модуле. Может быть их можно хранить как-то компактнее без потери скорости доступа??
Точно так же можно было обращаться к ScanLine битмапа, даже,.. наверное, чуток быстрее. В чем причина проблем с твоим кодом неохото разбираться..
Здравствуйте, Dimonka, Вы писали:
D> (
D> ((1,1,1,1,1,1,1,1),//строки выровнены все норм..
D> (1,0,1,1,1,0,1,1),
D> ,...............
D>Каждую такую строчку можно было как в старые добрые времена сделать одним байтом.
Критика уместна, но.. Каждую такую строчку мне все равно пришлось бы описать 4-мя байтами, 3 из которых были бы 0-ми... Так что объем хранимых данных уменьшился бы только в 2 раза, что по-моему не принципиально, вобщем что сделано то сделано...
D>Точно так же можно было обращаться к ScanLine битмапа, даже,.. наверное, чуток быстрее.
Согласен, что создавая VCL компонент логично пользоваться методами классов, которые эта самая VCL мне предоставляет...
Надо было бы сразу так и сделать.
А CreateDIBitmap корректно заработала, когда я явно указал, что я использую 2 цвета в полях biClrUsed = 2 и biClrImportant = 2. Забыл... =\
А вот второй вопрос все равно в силе.... Попробовал создать "тупой " ActiveX, который при создании заполняет битмап рандомными значениями и рисует его на своей канве в перегруженом методе Paint, и все работает... А этот компонент кроме рамки больше ничего не рисует... Есть ли какой-нить способ отлаживать ActiveX, расставив точки останова в исходном VCL классе? (я так подозреваю, что нет).
Да.. а при вызове в коде метода ParseLine(aIndex: Integer; const aLine: WideString; aCurPos1: Integer; aCurPos2: Integer); который автоматически транслирован Дельфи при создании AX,
например:
bbLCDX1.ParseLine(0, '0123456', 0, 0);
ActiveX валится с "Разрушительным сбоем"! Тут-то в чем дело???
Заранее благодарен за ответ.
Здравствуйте, siniypin, Вы писали:
S>Есть ли какой-нить способ отлаживать ActiveX, расставив точки останова в исходном VCL классе? (я так подозреваю, что нет).
Почему же есть. И даже два.
Обьясню прицип одного, помоему самого простого:
1. Делаете ProgectGroup
2. Добавляете в нее ActiveX рrоject
3. Компилите ActiveX
4. Зарегистрируйте OCX файл (если еще не зарегистрен): regsvr32 MyActiveXControl.ocx
2. Создаете, так называемый, Loader.exe — проэкт который подымает вашу ActiveX. В него пожключаете Вашу MyActiveXControl_TLB.pas.
В лоадере пишем код создания ActiveX:
procedure TForm1.Button1Click(Sender: TObject);
begin
FTestControl := TMyActiveX.Create(self); { TMyActiveX обьявлен в MyActiveXControl_TLB}
FTestControl.Parent := Self;
FTestControl.Align := alClient;
FTestControl.AxBorderStyle := 0;
end;
Вот и дебажим
Удачи!
Здравствуйте, Danchik, Вы писали:
D>[Skip]
D>Создайте ImageList, в который и накидай таблицу символов — проще будет работать с таблицей, да и не надо будет имплементить собственный Stotage.
А ImageList можно сделать доступным для пользователя, чтобы он свои картинки мог подгружать
Я может быть неправильно выразился... Вопрос был можно ли дебажить исходный VCL код при использовании созданного из него ActiveX. В приведенном Вами методе я дальше вызова методов DefaultInterface не проникаю... То есть вся работа компонента остается скрытой от меня.. Отсюда и вопросов столько.. =\
Здравствуйте, siniypin, Вы писали:
S>Я может быть неправильно выразился... Вопрос был можно ли дебажить исходный VCL код при использовании созданного из него ActiveX. В приведенном Вами методе я дальше вызова методов DefaultInterface не проникаю... То есть вся работа компонента остается скрытой от меня.. Отсюда и вопросов столько.. =\
Посмотри в опции линковки твоего OCX:
Попробуй поключать
Include TD32 debug info и
Include remote debug symbols (оба на всякий пожарный). И сделай
Build ALL.
Если у тебя Delphi 7 — проверь стоит ли у тебя update. В
этой веткеАвтор: Denis_TST
Дата: 10.11.05
обсуждалась подобная проблема и как искать патч.
насчет CreateDIBitmap.
Ты неверно инициализируешь
вот пример на VC+
typedef struct tagBITMAPINFO_MY
{
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[256];
}
BITMAPINFO_MY;
BITMAPINFO_MY m_bitInfo;
ZeroMemory(&m_bitInfo, sizeof(m_bitInfo));
m_bitInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
m_bitInfo.bmiHeader.biWidth = m_sizeTotal.cx;
m_bitInfo.bmiHeader.biHeight = m_sizeTotal.cy;
m_bitInfo.bmiHeader.biPlanes = 1;
m_bitInfo.bmiHeader.biBitCount = 8; // — т.е. 256 цветов (1,2,4,8,24,32)
m_bitInfo.bmiHeader.biCompression = BI_RGB;
m_bitInfo.bmiHeader.biSizeImage = ((m_bitInfo.bmiHeader.biWidth*m_bitInfo.bmiHeader.biBitCount+31)/32)*4*m_bitInfo.bmiHeader.biHeight;
memset(m_bitInfo.bmiColors, 0, sizeof(m_bitInfo.bmiColors));
// Init my colors
m_bitInfo.bmiColors[1].rgbBlue = 0;
m_bitInfo.bmiColors[1].rgbGreen = 0;
m_bitInfo.bmiColors[1].rgbRed = 0;
m_bitInfo.bmiColors[0].rgbBlue = 255;
m_bitInfo.bmiColors[0].rgbGreen = 255;
m_bitInfo.bmiColors[0].rgbRed = 255;
m_bitInfo.bmiColors[2].rgbBlue = 0;
m_bitInfo.bmiColors[2].rgbGreen = 255;
m_bitInfo.bmiColors[2].rgbRed = 0;
m_bitInfo.bmiColors[3].rgbBlue = 255;
m_bitInfo.bmiColors[3].rgbGreen = 0;
m_bitInfo.bmiColors[3].rgbRed = 0;
m_hBitmapSection = ::CreateDIBSection (m_dcMemoryToDraw.m_hDC, (BITMAPINFO*)&m_bitInfo.bmiHeader, DIB_RGB_COLORS, (PVOID*)&m_pvSection, 0, 0);
if ( !m_hBitmapSection ) exit(1);
//--------------------
Здесь создается секция, а по анологии создавай CreateDIBitmap