Базовый класс (простая линия) знает только об одной линии. а тут их 3. Метод выделения базового класса проверял попадание средней линии под мышь, тут нужно еще проверить линии выше и ниже.
Тогда, я могу предположить, следует использовать не наследование, а включение объектов класса "линия" в новый класс "СУПЕРЛИНИЯ".
Например, есть базовые классы:
1.) Примитив.
2.) Композитный объект.
Примитив - это линии, прямоугольники и всё прочее, что у вас является примитивом.
Композитный объект - это базовый класс для всех остальных "пользовательских" объектов.
Композитный объект содержит массив примитивов. Всё рисование сводится к добавлению примитива в массив и заданию его относительных координат.
При вызове метода отрисовки, метод-инициализатор переводит начальные координаты в абсолютные (ну, в случае с OpenGL, это не требуется).
Затем, производится проход по массиву объектов и вызов метода отрисовки каждого объекта.
Как вариант, перевод координат может делать класс "Примитив".
чето в пункты а и б я не въехал)).
б - это мой бред.
а - это просто "обведение" объектов ломаной. Точки отрезков ломаной берутся из "выступающих" точек примитивов. При том, что примитивы не пересекаются.
в - вроде понял, но он не честный. площадь прямоугольника может быть гораздо больше площади выделяемого объекта (если он вытянут и расположен по диагонали) - соответствеео выделение будет работать не правильно.
Он честный.

выделение должно быть честным - попадание части объекта в "квадрат" выделения, методы с boundingbox`ами годятся только для быстрого отсеивания сложных объектов которые точно не под мышью.
В случае, когда каждый примитив знает входит в него точка или нет, вряд ли это потребуется.
Хотя, для ускорения, вы правы: композитный объект может, на этапе формирования вычислять прямоугольник в который он входит. Проверка принадлежности точки объекту, в таком случае, сводится к проверке вхождения точки в этот прямоугольник. Если входит - уже производятся проверки для примитивов.
Кроме того, выделение происходит в 3д - т.к. если постоянно проекцировать объекты - будет очень тормозно.
Не знаю насчёт 3D. У меня сейчас никаких представлений на сей счёт не возникает.
Проекции, перекрытие, удалённость и прочее... Сложно.
Но, вообще, 3D - это всего лишь ещё одна плоскость. Т.е., всё возможно свести к X и Y.
пока планирую поведение с выделением только по границе (т.е. замкнутые объекты не выделяются по щелчку внутри, только на границе), из замкнутых объектов с заполнением у ченя пока только 3DFace, он недавно добавлен и еще толком не работает.
Если использовать схему выше, я думаю, что замкнутые объекты будут выделять себя сами, в каком месте не кликни. Главное использовать замкнутые примитивы (опять же, ориентируюсь на плоскость).
Насколько я понял в LCL класс TPanel не может обработать колесо мышки... как быть?
Будет ли работать так:
- Код: Выделить всё
TMyPanel = class(TPanel)
property OnMouseWheel;
property OnMouseWheelDown;
property OnMouseWheelUp;
end;
P.S.:
Нужно. но позже.
Позже я забыть могу. Да мне может и не до этого быть.

Выложу, на всякий. Если понадобится, будет под рукой.
glFont.h:
- Код: Выделить всё
//---------------------------------------------------------------------------
#ifndef glFontH
#define glFontH
//---------------------------------------------------------------------------
#include <windows.h>
//#include <wstring.h>
#include <gl\gl.h>
#include <Graphics.hpp>
//---------------------------------------------------------------------------
#include "../defines.h"
//---------------------------------------------------------------------------
class glFont
{
private:
bool FXCentered;
bool FYCentered;
protected:
GLuint FFontOffset;
GLYPHMETRICSFLOAT FGmf[256];
bool getXCentered() const {return FXCentered;};
void setXCentered(bool value) {FXCentered = value;};
bool getYCentered() const {return FYCentered;};
void setYCentered(bool value) {FYCentered = value;};
public:
glFont(HDC hDC, char* fontFace, GLfloat weight = 0,
int type = WGL_FONT_POLYGONS);
glFont(HDC hDC, TFont *font, GLfloat weight = 0,
int type = WGL_FONT_POLYGONS);
~glFont();
void __fastcall Put(const WideString& str) const;
// void put(const char ch);
public:
GLfloat __fastcall GetTextWidth(const WideString& str) const;
GLfloat __fastcall GetTextHeight(const WideString& str) const;
__property bool XCentered = {read = getXCentered, write = setXCentered};
__property bool YCentered = {read = getYCentered, write = setYCentered};
};
//---------------------------------------------------------------------------
#endif
glFont.cpp:
- Код: Выделить всё
//---------------------------------------------------------------------------
#pragma hdrstop
#include "glFont.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
glFont::glFont(HDC hDC, char* fontFace, GLfloat weight, int type) :
FXCentered(true), FYCentered(true)
{
HFONT hFont = CreateFontA(0/*height*/, 0/*width*/, 0/*aspect angle*/,
0/*angle*/, 0, FALSE/*italic*/, FALSE/*underline*/, FALSE/*strike-out*/,
RUSSIAN_CHARSET, OUT_TT_PRECIS/*render precision*/,
CLIP_DEFAULT_PRECIS /*clip precision*/, ANTIALIASED_QUALITY/*quality*/,
FF_DONTCARE|DEFAULT_PITCH, fontFace);
if (hFont == NULL) return;
FFontOffset = glGenLists(256);
HGDIOBJ old = SelectObject(hDC, hFont);
// wglUseFontBitmaps(hDC, 0, 256, fontOffset);
wglUseFontOutlines(hDC, 0, 256, FFontOffset, 0.1, weight,
type, FGmf);
SelectObject(hDC, old);
DeleteObject(hFont);
return;
}
//---------------------------------------------------------------------------
glFont::glFont(HDC hDC, TFont* font, GLfloat weight, int type):
FXCentered(true), FYCentered(true)
{
// HFONT hFont = CreateFontA(0/*height*/, 0/*width*/, 0/*aspect angle*/,
// 0/*angle*/, 0, FALSE/*italic*/, FALSE/*underline*/, FALSE/*strike-out*/,
// RUSSIAN_CHARSET, OUT_TT_PRECIS/*render precision*/, CLIP_DEFAULT_PRECIS/*clip precision*/,
// ANTIALIASED_QUALITY/*quality*/, FF_DONTCARE|DEFAULT_PITCH, fontFace);
if (font->Handle == NULL) return;
FFontOffset = glGenLists(256);
HGDIOBJ old = SelectObject(hDC, font->Handle);
// wglUseFontBitmaps(hDC, 0, 256, fontOffset);
wglUseFontOutlines(hDC, 0, 255, FFontOffset, 0.1, weight,
type, FGmf);
SelectObject(hDC, old);
// DeleteObject(font->Handle);
return;
}
//---------------------------------------------------------------------------
glFont::~glFont()
{
glDeleteLists(FFontOffset, 256);
}
//---------------------------------------------------------------------------
GLfloat __fastcall glFont::GetTextWidth(const WideString& str) const
{
GLfloat text_width = 0;
for (register int i = 0; i < str.Length(); i++)
text_width += FGmf[str[i]].gmfCellIncX;
return(text_width);
}
//---------------------------------------------------------------------------
GLfloat __fastcall glFont::GetTextHeight(const WideString& str) const
{
GLfloat text_height = 0;
for (register int i = 0; i < str.Length(); i++)
if (text_height < FGmf[str[i]].gmfBlackBoxY)
text_height = FGmf[str[i]].gmfBlackBoxY;
return(text_height);
}
//---------------------------------------------------------------------------
void __fastcall glFont::Put(const WideString &str) const
{
//glRasterPos3f(x, y, z);
if (FXCentered)
{
glTranslatef(-GetTextWidth(str) / 2, 0, 0);
}
if (FYCentered)
{
glTranslatef(0, -GetTextHeight(str) / 2, 0);
}
glPushAttrib(GL_LIST_BIT);
glListBase(FFontOffset);
glCallLists((GLsizei)str.Length(), GL_UNSIGNED_SHORT, _TEXT(str));
glPopAttrib();
}
//---------------------------------------------------------------------------
Увы, пока только под window$.
