Maks150988 Да, точно. Двумерный динамический массив это по сути одномерный динамический массив с указателями на одномерные дин. массивы. Причем эти массивы не обязаны лежать в памяти вместе, а могут быть разбросаны по оперативке как угодно. Т. о. в данном случае мы можем использовать только один большой одномерный дин. массив.
И кстати память под такие массивы выделяет менеджер памяти делфи, а вы, я вижу, пытаетесь использовать исключительно системный.
И кстати рисовать черным по черному, это оригинально
Остальные замечания в [more=коде.]
Код: [no]unit F_StatCtrlDib;
interface
uses
Windows, Messages, F_Windows;
procedure CreateVisualStatic(hWnd: HWND);
procedure RemoveVisualStatic(hWnd: HWND);
implementation
const
ID_TIMER = 101;
MAX_WIDTH = 89;
MAX_HEIGTH = 29;
type
TCtrlWndProc = function(hWnd: HWND; uMsg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
TbmpBits = Array[1..MAX_HEIGTH, 1..MAX_WIDTH] of TRGBQuad;
PbmpBits = ^TbmpBits;
P_CTRL_PRO = ^T_CTRL_PRO;
T_CTRL_PRO = packed record
CtrlProc: TCtrlWndProc;
//
hdcMem : HDC;
hbmMem : HBITMAP;
hbmOld : HBITMAP;
bmBits : PbmpBits; //Указатель на пиксели тоже храним
end;
var
pcp: P_CTRL_PRO;
//
procedure DrawGridLines(pcp: P_CTRL_PRO);
type
TBits = Array of TRGBQuad;
var
lpBits: TBits;
bmi : TBitmapInfo;
pixel : Integer;
procedure SetMemDCPixel(bits: TBits; X, Y: Integer);
begin
bits[Y*MAX_WIDTH+ X].rgbBlue := 0;
bits[Y*MAX_WIDTH+ X].rgbGreen := 255;
bits[Y*MAX_WIDTH+ X].rgbRed := 0;
bits[Y*MAX_WIDTH+ X].rgbReserved := 0;
end;
begin
//
{
with bmi.bmiHeader do
begin
biSize := SizeOf(bmi.bmiHeader);
biWidth := MAX_WIDTH;
biHeight := -MAX_HEIGTH;
biPlanes := 1;
biBitCount := 32;
biCompression := BI_RGB;
end;
SetLength(lpBits, MAX_HEIGTH * MAX_WIDTH);
GetDIBits(pcp.hdcMem, pcp.hbmMem, 0, MAX_HEIGTH, @lpBits[0], bmi, DIB_RGB_COLORS);
// left.
SetMemDCPixel(lpBits, 0, 0);
SetMemDCPixel(lpBits, 1, 0);
SetMemDCPixel(lpBits, 1, 10);
SetMemDCPixel(lpBits, 0, 12);
SetMemDCPixel(lpBits, 1, 12);
SetMemDCPixel(lpBits, 1, 14);
SetMemDCPixel(lpBits, 0, 24);
SetMemDCPixel(lpBits, 1, 24);
for pixel := 0 to (MAX_HEIGTH - 3) do
if not Odd(pixel) then
SetMemDCPixel(lpBits, 2, pixel);
// right.
for pixel := 0 to (MAX_HEIGTH - 3) do
if not Odd(pixel) then
SetMemDCPixel(lpBits, MAX_WIDTH - 3, pixel);
SetMemDCPixel(lpBits, MAX_WIDTH - 1, 0);
SetMemDCPixel(lpBits, MAX_WIDTH - 2, 0);
SetMemDCPixel(lpBits, MAX_WIDTH - 2, 10);
SetMemDCPixel(lpBits, MAX_WIDTH - 1, 12);
SetMemDCPixel(lpBits, MAX_WIDTH - 2, 12);
SetMemDCPixel(lpBits, MAX_WIDTH - 2, 14);
SetMemDCPixel(lpBits, MAX_WIDTH - 1, 24);
SetMemDCPixel(lpBits, MAX_WIDTH - 2, 24);
// bottom.
for pixel := 2 to (MAX_WIDTH - 3) do
if not Odd(pixel) then
SetMemDCPixel(lpBits, pixel, MAX_HEIGTH - 3);
SetMemDCPixel(lpBits, 10, MAX_HEIGTH - 2);
SetMemDCPixel(lpBits, 10, MAX_HEIGTH - 1);
SetMemDCPixel(lpBits, 18, MAX_HEIGTH - 2);
SetMemDCPixel(lpBits, 26, MAX_HEIGTH - 2);
SetMemDCPixel(lpBits, 34, MAX_HEIGTH - 2);
SetMemDCPixel(lpBits, 44, MAX_HEIGTH - 2);
SetMemDCPixel(lpBits, 44, MAX_HEIGTH - 1);
SetMemDCPixel(lpBits, 54, MAX_HEIGTH - 2);
SetMemDCPixel(lpBits, 62, MAX_HEIGTH - 2);
SetMemDCPixel(lpBits, 70, MAX_HEIGTH - 2);
SetMemDCPixel(lpBits, 78, MAX_HEIGTH - 2);
SetMemDCPixel(lpBits, 78, MAX_HEIGTH - 1);
//
SetDIBits(pcp.hdcMem, pcp.hbmMem, 0, MAX_HEIGTH, @lpBits[0], bmi, DIB_RGB_COLORS);
}
pcp.bmBits^[2, 2].rgbGreen:=255;
pcp.bmBits^[6, 2].rgbGreen:=255;
pcp.bmBits^[7, 6].rgbGreen:=255;
pcp.bmBits^[6, 7].rgbGreen:=255;
pcp.bmBits^[5, 7].rgbGreen:=255;
pcp.bmBits^[4, 7].rgbGreen:=255;
pcp.bmBits^[3, 7].rgbGreen:=255;
pcp.bmBits^[2, 7].rgbGreen:=255;
pcp.bmBits^[1, 6].rgbGreen:=255;
end;
//
function CtrlWndProc_WmPaint(pcp: P_CTRL_PRO; hWnd: HWND; uMsg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
var
ps: TPaintStruct;
begin
//
BeginPaint(hWnd, ps);
//
StretchBlt(ps.hdc, ps.rcPaint.Left, ps.rcPaint.Top, ps.rcPaint.Right, ps.rcPaint.Bottom,
pcp.hdcMem, 0, 0, MAX_WIDTH, MAX_HEIGTH, SRCCOPY); //DPI Aware
//
EndPaint(hWnd, ps);
//
Result := 0;
end;
//
function CtrlWndProc_WmTimer(pcp: P_CTRL_PRO; hWnd: HWND; uMsg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT;
var
dwStyle: DWORD;
begin
//
//Зачем тут это?
// CallWindowProcW(@pcp.CtrlProc, hWnd, WM_PRINTCLIENT, pcp.hdcMem, PRF_CLIENT);
//
//Достаточно вызвать один раз, после создания битмапа т к содержимое все равно не меняется
DrawGridLines(pcp);
//
dwStyle := RDW_INVALIDATE or RDW_UPDATENOW or RDW_NOERASE;
RedrawWindow(hWnd, nil, 0, dwStyle);
//
Result := 0;
end;
//
function CtrlWndProc_WmEraseBkgnd(pcp: P_CTRL_PRO; hWnd: HWND; uMsg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT;
begin
//
Result := 1;
end;
//
function StatWndProc(hWnd: HWND; uMsg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
begin
pcp := P_CTRL_PRO(GetWindowLongW(hWnd, GWL_USERDATA));
if (pcp = nil) then
begin
Result := DefWindowProcW(hWnd, uMsg, wParam, lParam);
Exit;
end;
case uMsg of
//
WM_DESTROY:
begin
RemoveVisualStatic(hWnd);
end;
//
WM_PRINTCLIENT,
WM_PAINT,
WM_UPDATEUISTATE:
begin
Result := CtrlWndProc_WmPaint(pcp, hWnd, uMsg, wParam, lParam);
end;
//
WM_TIMER:
begin
Result := CtrlWndProc_WmTimer(pcp, hWnd, uMsg, wParam, lParam);
end;
//
WM_ERASEBKGND:
begin
Result := CtrlWndProc_WmEraseBkgnd(pcp, hWnd, uMsg, wParam, lParam);
end;
else
Result := CallWindowProcW(@pcp.CtrlProc, hWnd, uMsg, wParam, lParam);
end;
end;
//
procedure CreateVisualStatic(hWnd: HWND);
var
hdcIn : HDC;
dwStyle: DWORD;
bmi : TBitmapInfo;
begin
RemoveVisualStatic(hWnd);
pcp := P_CTRL_PRO(HeapAlloc(GetProcessHeap, HEAP_ZERO_MEMORY, SizeOf(T_CTRL_PRO)));
ZeroMemory(pcp, SizeOf(T_CTRL_PRO));
pcp.CtrlProc := TCtrlWndProc(Pointer(GetWindowLongW(hWnd, GWL_WNDPROC)));
with bmi.bmiHeader do
begin
biSize := SizeOf(bmi.bmiHeader);
biWidth := MAX_WIDTH;
biHeight := -MAX_HEIGTH; //Изменили порядок строк
biPlanes := 1;
biBitCount := 32;
biCompression := BI_RGB;
end;
hdcIn := GetDC(hWnd);
pcp.hdcMem := CreateCompatibleDC(hdcIn); //Указатель нам еще понадобится при рисовании
pcp.hbmMem := CreateDIBSection(hdcIn, bmi, DIB_RGB_COLORS, Pointer(pcp.bmBits), 0, 0);
pcp.hbmOld := SelectObject(pcp.hdcMem, pcp.hbmMem);
ReleaseDC(hWnd, hdcIn);
dwStyle := SWP_NOMOVE or SWP_NOZORDER;
dwStyle := SWP_NOSIZE or dwStyle; //DPI Aware
SetWindowPos(hWnd, HWND_TOP, 0, 0, MAX_WIDTH, MAX_HEIGTH, dwStyle);
SetWindowLongW(hWnd, GWL_USERDATA, Longint(pcp));
SetWindowLongW(hWnd, GWL_WNDPROC, Longint(@StatWndProc));
SendmessageW(hWnd, WM_TIMER, 0, 0);
SetTimer(hWnd, ID_TIMER, 25, nil);
end;
//
procedure RemoveVisualStatic(hWnd: HWND);
var
dwStyle: DWORD;
begin
pcp := P_CTRL_PRO(GetWindowLongW(hWnd, GWL_USERDATA));
if (pcp <> nil) then
begin
//
if (pcp.hdcMem <> 0) then
begin
SelectObject(pcp.hdcMem, pcp.hbmOld);
DeleteObject(pcp.hbmMem);
DeleteDC(pcp.hdcMem);
end;
//
KillTimer(hWnd, ID_TIMER);
//
SetWindowLongW(hWnd, GWL_WNDPROC, Longint(@pcp.CtrlProc));
//
SetWindowLongW(hWnd, GWL_USERDATA, 0);
HeapFree(GetProcessHeap, 0, pcp);
//
dwStyle := RDW_INVALIDATE or RDW_UPDATENOW or RDW_NOERASE;
RedrawWindow(hWnd, nil, 0, dwStyle);
end;
end;
end.[/no]