#include "xy.h"
void XScale::onPaint(PAINTSTRUCT&ps) {
}
void YScale::onPaint(PAINTSTRUCT&ps) {
}
void Scale::distributeTicks(HDC dc) {
}
// Hier: siz.cx = Überhang (links und rechts), siz.cy = benötigte Höhe
void XScale::needSpace(HDC dc,SIZE&siz) const{
// TODO: Iteriere über alle Labels, füge Achsenbezeichnung hinzu
SelectFont(dc,font[0]);
GetTextExtentPoint32(dc,TEXT("X"),1,&siz);
siz.cx>>=1; // Hälfte
if (name && *name) siz.cy<<=1; // 2×
}
// Hier: siz.cx = benötigte Breite, siz.cy = Überhang (oben und unten)
void YScale::needSpace(HDC dc,SIZE&siz) const{
// TODO: Iteriere über alle Labels, füge Achsenbezeichnung hinzu
SelectFont(dc,font[0]);
GetTextExtentPoint32(dc,TEXT("0,0"),1,&siz);
siz.cx>>=1; // Hälfte
if (name && *name) siz.cy<<=1; // 2×
}
// XY-Graf
XY::XY(HWND Wnd):wnd(Wnd) {
xscale=new XScale(this);
yscales.push_back(new YScale(this));
}
void XY::onSize(int cx, int cy) {
HDC dc=GetDC(wnd);
SaveDC(dc);
SetRect(&rcPlot,0,0,cx,cy);
// Pass 1: Größe der Plot-Ränder bestimmen
int xextra=0,yextra=0;
SIZE siz;
xscale->needSpace(dc,siz);
rcPlot.bottom-=siz.cy;
xextra=siz.cx;
// Schleifenkonstruktion MSVC6
for(std::vector<YScale*>::iterator ysi=yscales.begin();ysi!=yscales.end();++ysi) {
YScale*ys=*ysi;
ys->needSpace(dc,siz);
if (ys->side&2) rcPlot.right-=siz.cx; else rcPlot.left+=siz.cx;
if (yextra<siz.cy) yextra=siz.cy;
}
if (rcPlot.left<xextra) rcPlot.left=xextra;
if (rcPlot.top<yextra) rcPlot.top=yextra;
if (rcPlot.right>cx-xextra) rcPlot.right=cx-xextra;
if (rcPlot.bottom>cx-yextra) rcPlot.bottom=cy-yextra;
// Pass 2: Skalen platzieren
SetRect(xscale,rcPlot.left,rcPlot.bottom,rcPlot.right,cy);
xscale->calcFO();
int l=rcPlot.left, r=rcPlot.right;
// Schleifenkonstruktion VC2008
for each(YScale*ys in yscales) {
ys->needSpace(dc,siz);
if (ys->side&2) {
SetRect(ys,r,rcPlot.top,r+siz.cx,rcPlot.bottom);
r+=siz.cx;
}else{
SetRect(ys,l-siz.cx,rcPlot.top,l,rcPlot.bottom);
l-=siz.cx;
}
ys->calcFO();
}
// Pass 3: Skalierungen aktualisieren
RestoreDC(dc,-1);
ReleaseDC(wnd,dc);
}
void XY::onPaint(PAINTSTRUCT&ps) {
Rect rcClient;
GetClientRect(wnd,&rcClient);
MoveToEx(ps.hdc,rcClient.left,rcClient.top,0);
LineTo(ps.hdc,rcClient.right,rcClient.bottom);
MoveToEx(ps.hdc,rcPlot.left,rcPlot.bottom,0);
LineTo(ps.hdc,rcPlot.right,rcPlot.top);
xscale->onPaint(ps);
// Schleifenkonstruktion MSVC2017
// for(auto ys:yscales) ys->onPaint(ps); // alle Y-Skalen
for each (YScale*ys in yscales) ys->onPaint(ps); // alle Y-Skalen
}
LRESULT XY::wndproc(UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_SIZE: onSize(GET_X_LPARAM(lParam),GET_Y_LPARAM(lParam)); return 0;
case WM_PAINT: {
PAINTSTRUCT ps;
BeginPaint(wnd,&ps);
onPaint(ps);
EndPaint(wnd,&ps);
}return 0;
case WM_PRINTCLIENT: {
PAINTSTRUCT ps;
ps.hdc=(HDC)wParam;
ps.fErase=TRUE;
GetClientRect(wnd,&ps.rcPaint);
onPaint(ps);
}return 0;
}
return DefWindowProc(wnd,msg,wParam,lParam);
}
LRESULT CALLBACK XY::wndproc(HWND Wnd, UINT msg, WPARAM wParam, LPARAM lParam) {
XY*self=(XY*)GetWindowLong(Wnd,0);
if (!self) {
self=new XY(Wnd);
SetWindowLong(Wnd,0,(LONG_PTR)self);
}
LRESULT ret=self->wndproc(msg,wParam,lParam);
if (msg==WM_NCDESTROY) delete self;
return ret;
}
BOOL XY::init() {
static const WNDCLASS wc={
CS_DBLCLKS|CS_HREDRAW|CS_VREDRAW|CS_PARENTDC,
wndproc,
0,
sizeof(XY*),
0,
0,
0,
HBRUSH(COLOR_WINDOW+1),
0,MAKEINTRESOURCE(42)
};
return RegisterClass(&wc);
}
Vorgefundene Kodierung: UTF-8 | 0
|