Home » U++ Library support » Draw, Display, Images, Bitmaps, Icons » RectTracker filled with black
RectTracker filled with black [message #14119] |
Wed, 13 February 2008 06:54  |
cbpporter
Messages: 1427 Registered: September 2007
|
Ultimate Contributor |
|
|
Hi!
I've been using RectTracker for a while now and I'm quite happy with it because it removes the need for manual mouse move and up handling, the actual drawing, managing capture, etc. But the limitation of the resulting rect to a specified quadrant is no longer suited to my need, so I've added 4 little lines to allow the use of ALIGN_NULL for tx and ty parameters in RectTracker::TrackRect to mean that the resulting rect is freed from constrains, even though by it's definition, it could possibly be "empty".
The problem is that if it is outside one given quadrant, the drawn rect becomes filled with black, as opposed to just an outline. Does anybody have any idea why this happens?
Here is my moddified RectTracker:
void RectTracker::MouseMove(Point, dword)
{
Point p = GetMousePos();
rect = org;
if(tx == ALIGN_CENTER && ty == ALIGN_CENTER) {
int x = org.left - op.x + p.x;
int y = org.top - op.y + p.y;
if(x + org.Width() > maxrect.right)
x = maxrect.right - org.Width();
if(x < maxrect.left)
x = maxrect.left;
if(y + org.Height() > maxrect.bottom)
y = maxrect.bottom - org.Height();
if(y < maxrect.top)
y = maxrect.top;
rect = RectC(x, y, org.Width(), org.Height());
}
else {
if(tx == ALIGN_LEFT) {
rect.left = max(org.left - op.x + p.x, maxrect.left);
rect.left = minmax(rect.left, rect.right - maxsize.cx, rect.right - minsize.cx);
}
if(tx == ALIGN_RIGHT) {
rect.right = min(org.right - op.x + p.x, maxrect.right);
rect.right = minmax(rect.right, rect.left + minsize.cx, rect.left + maxsize.cx);
}
if(ty == ALIGN_TOP) {
rect.top = max(org.top - op.y + p.y, maxrect.top);
rect.top = minmax(rect.top, rect.bottom - maxsize.cy, rect.bottom - minsize.cy);
}
if(ty == ALIGN_BOTTOM) {
rect.bottom = min(org.bottom - op.y + p.y, maxrect.bottom);
rect.bottom = minmax(rect.bottom, rect.top + minsize.cy, rect.top + maxsize.cy);
}
if(tx == ALIGN_NULL)
rect.right = min(org.right - op.x + p.x, maxrect.right);
if(ty == ALIGN_NULL)
rect.bottom = min(org.bottom - op.y + p.y, maxrect.bottom);
if(keepratio) {
int cy = org.Width() ? rect.Width() * org.Height() / org.Width() : 0;
int cx = org.Height() ? rect.Height() * org.Width() / org.Height() : 0;
if(tx == ALIGN_BOTTOM && ty == ALIGN_RIGHT) {
Size sz = rect.Size();
if(cx > sz.cx)
rect.right = rect.left + cx;
else
rect.bottom = rect.top + cy;
}
else
if(tx == ALIGN_RIGHT)
rect.bottom = rect.top + cy;
else
if(ty == ALIGN_BOTTOM)
rect.right = rect.left + cx;
}
}
if(rect != o) {
rect = Round(rect);
if(rect != o) {
DrawRect(o, rect);
sync(rect);
o = rect;
}
}
}
|
|
|
|
Re: RectTracker filled with black [message #14122 is a reply to message #14120] |
Wed, 13 February 2008 12:13   |
mrjt
Messages: 705 Registered: March 2007 Location: London
|
Contributor |
|
|
DrawDragRect doesn't work properly with backwards rectangles.
...
if(tx == ALIGN_NULL) {
rect.right = min(org.right - op.x + p.x, maxrect.right);
if (rect.right < rect.left) Swap(rect.left, rect.right);
}
if(ty == ALIGN_NULL) {
rect.bottom = min(org.bottom - op.y + p.y, maxrect.bottom);
if (rect.bottom < rect.top) Swap(rect.top, rect.bottom);
}
...
KeepRatio won't work properly, but since it only works correctly with ALIGN_RIGHT/ALIGN_BOTTOM anyway I don't see this as a major problem.
For a test case just change the default behaviour in RectTracker example (ie no control keys) to ALIGN_NULL/ALIGN_NULL.
I love looking through Upp source, there is always something new and cool to find . For instance, what is the purpose of ViewDraw? Could I use it to do drawing over a TopWindow full of controls? I've been looking for a way to do that for a while.
[Updated on: Wed, 13 February 2008 12:33] Report message to a moderator
|
|
|
|
|
Re: RectTracker filled with black [message #14210 is a reply to message #14128] |
Wed, 20 February 2008 09:33   |
cbpporter
Messages: 1427 Registered: September 2007
|
Ultimate Contributor |
|
|
Since nobody commented on the coordinate relation between mouse cursor position/rect coordinates and the way the drawn rect visually "touches" the cursor (and also KeepRation(true) seems to add another difference of 1 pixel to the extent of the visual rect), I guess it's safe to assume that this is not an issue for anybody else and it will remain as is.
Then here are the proposed changed to RectTracker, so that ALIGN_NULL will work:
void RectTracker::MouseMove(Point, dword)
{
Point p = GetMousePos();
rect = org;
if(tx == ALIGN_CENTER && ty == ALIGN_CENTER) {
int x = org.left - op.x + p.x;
int y = org.top - op.y + p.y;
if(x + org.Width() > maxrect.right)
x = maxrect.right - org.Width();
if(x < maxrect.left)
x = maxrect.left;
if(y + org.Height() > maxrect.bottom)
y = maxrect.bottom - org.Height();
if(y < maxrect.top)
y = maxrect.top;
rect = RectC(x, y, org.Width(), org.Height());
}
else {
if(tx == ALIGN_LEFT) {
rect.left = max(org.left - op.x + p.x, maxrect.left);
rect.left = minmax(rect.left, rect.right - maxsize.cx, rect.right - minsize.cx);
}
if(tx == ALIGN_RIGHT) {
rect.right = min(org.right - op.x + p.x, maxrect.right);
rect.right = minmax(rect.right, rect.left + minsize.cx, rect.left + maxsize.cx);
}
if(ty == ALIGN_TOP) {
rect.top = max(org.top - op.y + p.y, maxrect.top);
rect.top = minmax(rect.top, rect.bottom - maxsize.cy, rect.bottom - minsize.cy);
}
if(ty == ALIGN_BOTTOM) {
rect.bottom = min(org.bottom - op.y + p.y, maxrect.bottom);
rect.bottom = minmax(rect.bottom, rect.top + minsize.cy, rect.top + maxsize.cy);
}
if(tx == ALIGN_NULL) {
rect.right = min(org.right - op.x + p.x, maxrect.right);
}
if(ty == ALIGN_NULL) {
rect.bottom = min(org.bottom - op.y + p.y, maxrect.bottom);
}
if(keepratio) {
int cy = org.Width() ? rect.Width() * org.Height() / org.Width() : 0;
int cx = org.Height() ? rect.Height() * org.Width() / org.Height() : 0;
if(tx == ALIGN_BOTTOM && ty == ALIGN_RIGHT) {
Size sz = rect.Size();
if(cx > sz.cx)
rect.right = rect.left + cx;
else
rect.bottom = rect.top + cy;
}
else
if(tx == ALIGN_RIGHT)
rect.bottom = rect.top + cy;
else
if(ty == ALIGN_BOTTOM)
rect.right = rect.left + cx;
}
}
if(rect != o) {
rect = Round(rect);
if(rect != o) {
DrawRect(o, rect);
sync(rect);
o = rect;
}
}
}
void RectTracker::DrawRect(Rect r1, Rect r2)
{
if(ty < 0) {
r1.left = r1.right - 1;
r2.left = r2.right - 1;
}
if(tx < 0) {
r1.top = r1.bottom - 1;
r2.top = r2.bottom - 1;
}
Rect c = clip & GetMaster().GetSize();
if (r1.right < r1.left) Swap(r1.left, r1.right);
if (r1.bottom < r1.top) Swap(r1.top, r1.bottom);
if (r2.right < r2.left) Swap(r2.left, r2.right);
if (r2.bottom < r2.top) Swap(r2.top, r2.bottom);
if(animation) {
int nanim = (GetTickCount() / animation) % 8;
DrawDragRect(GetMaster(), Rect(0, 0, 0, 0), r2, c, width, color, sGetAniPat(pattern, nanim));
DrawDragRect(GetMaster(), r1, Rect(0, 0, 0, 0), c, width, color, sGetAniPat(pattern, panim));
panim = nanim;
}
else
DrawDragRect(GetMaster(), r1, r2, c, width, color, pattern);
}
|
|
|
Re: RectTracker filled with black [message #14216 is a reply to message #14210] |
Wed, 20 February 2008 10:55   |
mrjt
Messages: 705 Registered: March 2007 Location: London
|
Contributor |
|
|
This would be my suggested version:
void RectTracker::MouseMove(Point, dword)
{
Point p = GetMousePos();
rect = org;
if(tx == ALIGN_CENTER && ty == ALIGN_CENTER) {
int x = org.left - op.x + p.x;
int y = org.top - op.y + p.y;
if(x + org.Width() > maxrect.right)
x = maxrect.right - org.Width();
if(x < maxrect.left)
x = maxrect.left;
if(y + org.Height() > maxrect.bottom)
y = maxrect.bottom - org.Height();
if(y < maxrect.top)
y = maxrect.top;
rect = RectC(x, y, org.Width(), org.Height());
}
else {
if(tx == ALIGN_LEFT) {
rect.left = max(org.left - op.x + p.x, maxrect.left);
rect.left = minmax(rect.left, rect.right - maxsize.cx, rect.right - minsize.cx);
}
if(tx == ALIGN_RIGHT) {
rect.right = min(org.right - op.x + p.x, maxrect.right);
rect.right = minmax(rect.right, rect.left + minsize.cx, rect.left + maxsize.cx);
}
if(ty == ALIGN_TOP) {
rect.top = max(org.top - op.y + p.y, maxrect.top);
rect.top = minmax(rect.top, rect.bottom - maxsize.cy, rect.bottom - minsize.cy);
}
if(ty == ALIGN_BOTTOM) {
rect.bottom = min(org.bottom - op.y + p.y, maxrect.bottom);
rect.bottom = minmax(rect.bottom, rect.top + minsize.cy, rect.top + maxsize.cy);
}
if(tx == ALIGN_NULL) {
rect.right = min(org.right - op.x + p.x, maxrect.right);
if (rect.right < rect.left) {
Swap(rect.right, rect.left);
rect.InflateHorz(1);
}
}
if(ty == ALIGN_NULL) {
rect.bottom = min(org.bottom - op.y + p.y, maxrect.bottom);
if (rect.bottom < rect.top) {
Swap(rect.bottom, rect.top);
rect.InflateVert(1);
}
}
if(keepratio) {
int cy = org.Width() ? rect.Width() * org.Height() / org.Width() : 0;
int cx = org.Height() ? rect.Height() * org.Width() / org.Height() : 0;
if(tx == ALIGN_BOTTOM && ty == ALIGN_RIGHT) {
Size sz = rect.Size();
if(cx > sz.cx)
rect.right = rect.left + cx;
else
rect.bottom = rect.top + cy;
}
else
if(tx == ALIGN_RIGHT)
rect.bottom = rect.top + cy;
else
if(ty == ALIGN_BOTTOM)
rect.right = rect.left + cx;
}
}
if(rect != o) {
rect = Round(rect);
if(rect != o) {
DrawRect(o, rect);
sync(rect);
o = rect;
}
}
}
It fixes the cursor alignment problem. I also believe that this is the correct place to modify the coordinates, as doing so before drawing means that the final rectangle is inaccurate.
IMO if you really need to have the final rectangle backwards I think you should compare and switch it after getting the final rect back.
[Updated on: Wed, 20 February 2008 11:13] Report message to a moderator
|
|
|
|
|
|
|
|
|
|
|
|
Re: RectTracker filled with black [message #14532 is a reply to message #14517] |
Fri, 29 February 2008 15:08   |
cbpporter
Messages: 1427 Registered: September 2007
|
Ultimate Contributor |
|
|
cbpporter wrote on Thu, 28 February 2008 12:12 |
OK, I'm giving up on RectTracker and doing it manually with mouse events and GetCapture(). I just can't get it to behave as as want it.
|
OK, I seems that U++ is having an undesired effect on me. I can no longer choose the easy way so easily . I was writing my manual code, and even though it was easy and worked fine, I felt it as highly redundant since there was already that RectTracker class.
So I sat down and managed to adapt it to my needs. I'm not posting the result, because I think it is not that general, it is more suited for graphics applications with precise cursor interaction, and also you have to adjust the coordinates returned by Track a little.
But there are still a couple of thing I would like to note:
1. I used ViewDraw and strangely, the drawings remain on my form even after it got covered by other windows. Does ViewDraw feature any cache or backbuffer?
2. In the code proposed by mrjt, I have found that the InflateVert(1) and InflateHorz(1) introduce a 1 pixel imprecision between mouse cursor, rect coordinates and visual representation of the drawn drag rect.
I have added include the test case I use to test coordinates.
-
Attachment: RectTest.rar
(Size: 1.45KB, Downloaded 422 times)
|
|
|
|
|
|
Goto Forum:
Current Time: Fri May 09 22:22:00 CEST 2025
Total time taken to generate the page: 0.03576 seconds
|