如何更改 canvas 区域的颜色
How to change a color in an area of a canvas
我尝试在 TCanvas 上单击并拖动,然后在向下拖动时将背景颜色更改为 clHighlight,如果要反转拖动方向,则将其更改回 clWhite。如果你点击你正在阅读的这段文字并向下或向上拖动,几乎会发生什么,反正都是一样的想法。我已经从这个 link
中收集到了我能收集到的东西
自从我第一次发布此代码以来,我已经对下面的代码进行了大量编辑,下面的代码现在完成了我打算做的事情,除了如果你不按甚至速度,这是不可接受的。如果你真的快速上下移动鼠标,它肯定会搞砸。如果你移动鼠标
以稳定的速度运行良好,这让我担心这个问题可能没有解决方案。我将继续关注这一点,如果有人有任何建议,那就太好了。我还遇到了一些 "Out of resources" 错误,还不确定这是怎么回事,我正在释放位图,没有涉及我所知道的其他资源。
下面的代码是在一个MouseMove event.srect是在TImage的Canvas中选中的矩形。 drect 与转换为 0,0 的 srect 相同。 bm1 包含使用 CopyRect 从 TImage 的 Canvas 复制的选定矩形。 bm2 包含 bm1,使用 BrushCopy 将 clWhite(背景)更改为 clHighlight(或相反)。然后使用 BitBlt 将 bm2 复制回原始 TImage 的选定矩形。
// vp is derived from TImage
if (Y > sel_data->_last_y)
{
TRect srect = Rect(sel_data->_rect.Left,sel_data->_last_y,sel_data->_rect.Right, Y);
TRect drect = Rect(sel_data->_rect.Left,0,sel_data->_rect.Right, sel_data->_rect.Height() - 1);
Graphics::TBitmap* bm1 = new Graphics::TBitmap;
bm1->Width = srect.Width();
bm1->Height = srect.Height();
Graphics::TBitmap* bm2 = new Graphics::TBitmap;
bm2->Width = srect.Width();
bm2->Height = srect.Height();
bm1->Canvas->CopyRect(drect, vp->Canvas, srect);
bm2->Canvas->Brush->Color = clHighlight;
bm2->Canvas->BrushCopy(drect, bm1, drect, clWindow);
BitBlt(vp->Canvas->Handle, srect.Left, srect.Top, srect.Width(), srect.Height(),
bm2->Canvas->Handle, 0, 0, SRCCOPY);
vp->Refresh();
delete bm1;
delete bm2;
}
else if (Y < sel_data->_last_y)
{
TRect srect = Rect(sel_data->_rect.Left, Y,sel_data->_rect.Right, sel_data->_last_y);
TRect drect = Rect(sel_data->_rect.Left,0,sel_data->_rect.Right, sel_data->_rect.Height() - 1);
Graphics::TBitmap* bm1 = new Graphics::TBitmap;
bm1->Width = srect.Width();
bm1->Height = srect.Height();
Graphics::TBitmap* bm2 = new Graphics::TBitmap;
bm2->Width = srect.Width();
bm2->Height = srect.Height();
bm1->Canvas->CopyRect(drect, vp->Canvas, srect);
bm2->Canvas->Brush->Color = clWhite;
bm2->Canvas->BrushCopy(drect, bm1, drect, clHighlight);
int w = srect.Width();
int h = srect.Height();
BitBlt(vp->Canvas->Handle, srect.Left, srect.Top, w, h, bm2->Canvas->Handle, 0, 0, SRCCOPY);
vp->Refresh();
delete bm1;
delete bm2;
}
sel_data->_last_y = Y;
}
这就是我的最终结果,据我所知,所有问题都已修复,我包括了整个 MouseMove 事件处理程序。上面提到的 link 提示我需要一个 CopyRect、一个 BrushCopy,然后是一个 BitBlt。
void __fastcall Tviewer_ui::viewerPageMouseMove(TObject *Sender, TShiftState Shift, int X, int Y)
{
if (_selecting)
{
TColor to_color = 0;
TColor from_color = 0;
Tviewer_page* vp = static_cast<Tviewer_page *>(Sender);
Tsel_data* sel_data = &vp->_sel_datas[vp->_c_sel];
// Scroll window if needed
int sb_pos = _scrollBox->VertScrollBar->Position;
if (Y > sb_pos - vp->_top + _scrollBox->Height - 10)
_scrollBox->VertScrollBar->Position += 10;
else
if (Y < sb_pos - vp->_top + 10)
_scrollBox->VertScrollBar->Position -= 10;
int y1 = 0;
int y2 = 0;
if (Y > sel_data->_start_y)
{
if (Y > sel_data->_last_y)
{
y1 = sel_data->_last_y;
y2 = Y;
from_color = clWhite;
to_color = clHighlight;
}
else if (Y < sel_data->_last_y)
{
y1 = Y;
y2 = sel_data->_last_y;
from_color = clHighlight;
to_color = clWhite;
}
sel_data->_rect.Bottom = Y;
}
else if (Y < sel_data->_start_y)
{
if (Y < sel_data->_last_y)
{
y1 = Y;
y2 = sel_data->_last_y;
from_color = clWhite;
to_color = clHighlight;
}
else if (Y > sel_data->_last_y)
{
y1 = sel_data->_last_y;
y2 = Y;
from_color = clHighlight;
to_color = clWhite;
}
sel_data->_rect.Top = Y;
}
int height = abs(y1 - y2);
if (height > 0)
{
TRect srect = Rect(sel_data->_rect.Left, y1, sel_data->_rect.Right, y2);
int width = srect.Width();
TRect drect = Rect(sel_data->_rect.Left,0,sel_data->_rect.Right, height);
Graphics::TBitmap* bm1 = new Graphics::TBitmap;
bm1->Width = width;
bm1->Height = height;
Graphics::TBitmap* bm2 = new Graphics::TBitmap;
bm2->Width = width;
bm2->Height = height;
bm1->Canvas->CopyRect(drect, vp->Canvas, srect);
bm2->Canvas->Brush->Color = to_color;
bm2->Canvas->BrushCopy(drect, bm1, drect, from_color);
BitBlt(vp->Canvas->Handle, srect.Left, srect.Top, width, height, bm2->Canvas->Handle, 0, 0, SRCCOPY);
vp->Refresh();
delete bm1;
delete bm2;
}
sel_data->_last_y = Y;
}
}
我尝试在 TCanvas 上单击并拖动,然后在向下拖动时将背景颜色更改为 clHighlight,如果要反转拖动方向,则将其更改回 clWhite。如果你点击你正在阅读的这段文字并向下或向上拖动,几乎会发生什么,反正都是一样的想法。我已经从这个 link
中收集到了我能收集到的东西自从我第一次发布此代码以来,我已经对下面的代码进行了大量编辑,下面的代码现在完成了我打算做的事情,除了如果你不按甚至速度,这是不可接受的。如果你真的快速上下移动鼠标,它肯定会搞砸。如果你移动鼠标 以稳定的速度运行良好,这让我担心这个问题可能没有解决方案。我将继续关注这一点,如果有人有任何建议,那就太好了。我还遇到了一些 "Out of resources" 错误,还不确定这是怎么回事,我正在释放位图,没有涉及我所知道的其他资源。
下面的代码是在一个MouseMove event.srect是在TImage的Canvas中选中的矩形。 drect 与转换为 0,0 的 srect 相同。 bm1 包含使用 CopyRect 从 TImage 的 Canvas 复制的选定矩形。 bm2 包含 bm1,使用 BrushCopy 将 clWhite(背景)更改为 clHighlight(或相反)。然后使用 BitBlt 将 bm2 复制回原始 TImage 的选定矩形。
// vp is derived from TImage
if (Y > sel_data->_last_y)
{
TRect srect = Rect(sel_data->_rect.Left,sel_data->_last_y,sel_data->_rect.Right, Y);
TRect drect = Rect(sel_data->_rect.Left,0,sel_data->_rect.Right, sel_data->_rect.Height() - 1);
Graphics::TBitmap* bm1 = new Graphics::TBitmap;
bm1->Width = srect.Width();
bm1->Height = srect.Height();
Graphics::TBitmap* bm2 = new Graphics::TBitmap;
bm2->Width = srect.Width();
bm2->Height = srect.Height();
bm1->Canvas->CopyRect(drect, vp->Canvas, srect);
bm2->Canvas->Brush->Color = clHighlight;
bm2->Canvas->BrushCopy(drect, bm1, drect, clWindow);
BitBlt(vp->Canvas->Handle, srect.Left, srect.Top, srect.Width(), srect.Height(),
bm2->Canvas->Handle, 0, 0, SRCCOPY);
vp->Refresh();
delete bm1;
delete bm2;
}
else if (Y < sel_data->_last_y)
{
TRect srect = Rect(sel_data->_rect.Left, Y,sel_data->_rect.Right, sel_data->_last_y);
TRect drect = Rect(sel_data->_rect.Left,0,sel_data->_rect.Right, sel_data->_rect.Height() - 1);
Graphics::TBitmap* bm1 = new Graphics::TBitmap;
bm1->Width = srect.Width();
bm1->Height = srect.Height();
Graphics::TBitmap* bm2 = new Graphics::TBitmap;
bm2->Width = srect.Width();
bm2->Height = srect.Height();
bm1->Canvas->CopyRect(drect, vp->Canvas, srect);
bm2->Canvas->Brush->Color = clWhite;
bm2->Canvas->BrushCopy(drect, bm1, drect, clHighlight);
int w = srect.Width();
int h = srect.Height();
BitBlt(vp->Canvas->Handle, srect.Left, srect.Top, w, h, bm2->Canvas->Handle, 0, 0, SRCCOPY);
vp->Refresh();
delete bm1;
delete bm2;
}
sel_data->_last_y = Y;
}
这就是我的最终结果,据我所知,所有问题都已修复,我包括了整个 MouseMove 事件处理程序。上面提到的 link 提示我需要一个 CopyRect、一个 BrushCopy,然后是一个 BitBlt。
void __fastcall Tviewer_ui::viewerPageMouseMove(TObject *Sender, TShiftState Shift, int X, int Y)
{
if (_selecting)
{
TColor to_color = 0;
TColor from_color = 0;
Tviewer_page* vp = static_cast<Tviewer_page *>(Sender);
Tsel_data* sel_data = &vp->_sel_datas[vp->_c_sel];
// Scroll window if needed
int sb_pos = _scrollBox->VertScrollBar->Position;
if (Y > sb_pos - vp->_top + _scrollBox->Height - 10)
_scrollBox->VertScrollBar->Position += 10;
else
if (Y < sb_pos - vp->_top + 10)
_scrollBox->VertScrollBar->Position -= 10;
int y1 = 0;
int y2 = 0;
if (Y > sel_data->_start_y)
{
if (Y > sel_data->_last_y)
{
y1 = sel_data->_last_y;
y2 = Y;
from_color = clWhite;
to_color = clHighlight;
}
else if (Y < sel_data->_last_y)
{
y1 = Y;
y2 = sel_data->_last_y;
from_color = clHighlight;
to_color = clWhite;
}
sel_data->_rect.Bottom = Y;
}
else if (Y < sel_data->_start_y)
{
if (Y < sel_data->_last_y)
{
y1 = Y;
y2 = sel_data->_last_y;
from_color = clWhite;
to_color = clHighlight;
}
else if (Y > sel_data->_last_y)
{
y1 = sel_data->_last_y;
y2 = Y;
from_color = clHighlight;
to_color = clWhite;
}
sel_data->_rect.Top = Y;
}
int height = abs(y1 - y2);
if (height > 0)
{
TRect srect = Rect(sel_data->_rect.Left, y1, sel_data->_rect.Right, y2);
int width = srect.Width();
TRect drect = Rect(sel_data->_rect.Left,0,sel_data->_rect.Right, height);
Graphics::TBitmap* bm1 = new Graphics::TBitmap;
bm1->Width = width;
bm1->Height = height;
Graphics::TBitmap* bm2 = new Graphics::TBitmap;
bm2->Width = width;
bm2->Height = height;
bm1->Canvas->CopyRect(drect, vp->Canvas, srect);
bm2->Canvas->Brush->Color = to_color;
bm2->Canvas->BrushCopy(drect, bm1, drect, from_color);
BitBlt(vp->Canvas->Handle, srect.Left, srect.Top, width, height, bm2->Canvas->Handle, 0, 0, SRCCOPY);
vp->Refresh();
delete bm1;
delete bm2;
}
sel_data->_last_y = Y;
}
}