Source file: /~heha/hs/wmfview.zip/src/show.cpp

#include "wmfview.h"
#include <math.h>

// für Rastergitter o.ä.
static void Line(HDC dc, int x1, int y1, int x2, int y2) {
 POINT pt[2]={{x1,y1},{x2,y2}};
 Polyline(dc,pt,2);
}

int CurZoom;	// Zoom in Tausendstel, wenn positiv (stets isotrop), oder Sonderfunktion wenn <=0

int round(float f) {
 return (int)floor(f+0.5);
}

cRECT rcFrame;	// Vorgesehene Rahmengröße, in Metadatei-Einheiten
cRECT rcBBox;	// Vorgefundene Metadatei-Ausdehnung (nach Enumeration aller Elemente)
		// Vorläufig gleich rcFrame
POINT dpi;	// Vorgefundene Skalierung [Pixel pro Zoll]
POINT scr;	// Bildschirmauflösung (Pixel pro Zoll)

static void HandleWmScroll(HWND Wnd, int iBar, int iScrollCode) {
 SCROLLINFO si;
 si.cbSize=sizeof(si);
 si.fMask=SIF_ALL;
 GetScrollInfo(Wnd,iBar,&si);
 int diff=si.nPos;	// alte Position
 switch (iScrollCode) {
  case SB_LINELEFT:   si.nPos-=si.nPage>>4; break;
  case SB_LINERIGHT:  si.nPos+=si.nPage>>4; break;
  case SB_PAGELEFT:   si.nPos-=si.nPage; break;
  case SB_PAGERIGHT:  si.nPos+=si.nPage; break;
  case SB_LEFT:       si.nPos =si.nMin; break;
  case SB_RIGHT:      si.nPos =si.nMax; break;
  case SB_THUMBTRACK: si.nPos =si.nTrackPos; break;
 }
 si.fMask=SIF_POS;
 SetScrollInfo(Wnd,iBar,&si,TRUE);
 GetScrollInfo(Wnd,iBar,&si);
 diff-=si.nPos;		// neue Position subtrahieren
 ScrollWindow(Wnd,iBar?0:diff,iBar?diff:0,NULL,NULL);
}

// Schiebt Rollbalken um <dist>, liefert tatsächlich geschobene <dist> (bei Anschlägen links/rechts)
static int MoveScrollPos(HWND Wnd, int iBar, int dist) {
 int pos=GetScrollPos(Wnd,iBar);
 SetScrollPos(Wnd,iBar,pos-dist,TRUE);
 return pos-GetScrollPos(Wnd,iBar);
}

static int GetOrg(const SCROLLINFO&si, int page) {
 int ovr=page-(si.nMax-si.nMin);	// negativ bei sichtbaren Rollbalken
 return ovr<0?-si.nPos:(ovr>>1)-si.nMin;	// ohne Rollbalken Grafik mittig platzieren
}

// Koordinate der linken oberen Ecke der Grafik bestimmen, in Client-Koordinaten
// Die liegt - bei Vergrößerung - üblicherweise bei negativen Koordinaten
static void OffsetDC(HWND Wnd, HDC dc) {
 cRECT r;
 GetClientRect(Wnd,&r);
 SCROLLINFO si;
 si.cbSize=sizeof(si);
 si.fMask=SIF_RANGE|SIF_POS;
 GetScrollInfo(Wnd,SB_HORZ,&si);
 int x=GetOrg(si,r.right);
 GetScrollInfo(Wnd,SB_VERT,&si);
 int y=GetOrg(si,r.bottom);
 SetViewportOrgEx(dc,x,y,NULL);
 SetBrushOrgEx(dc,x,y,NULL);
}

typedef struct {
 HTREEITEM h;
}EMFDRAW;

static int _stdcall EmfDrawProc(HDC dc, HANDLETABLE *ht, const ENHMETARECORD *mr,
  int cObj, LPARAM lParam) {
 EMFDRAW *ed=(EMFDRAW*)lParam;
 TVITEM item;
 DECODEINFO *di;
 int i;
 PlayEnhMetaFileRecord(dc,ht,mr,cObj);
 item.mask=TVIF_PARAM;
 item.hItem=ed->h;
 if (TreeView_GetItem(hContent,&item)) {
  di=(DECODEINFO*)item.lParam;
  if (di->Flags&DI_SELECTED) {
   SaveDC(dc);
   SelectPen(dc,GetStockPen(BLACK_PEN));
   SelectBrush(dc,GetStockBrush(BLACK_BRUSH));
   for (i=0; i<di->nPoints; i++) {
    if (di->Flags&DI_POINTS) Rectangle(dc,
      di->PointList.ps[i].x-4,
      di->PointList.ps[i].y-4,
      di->PointList.ps[i].x+4,
      di->PointList.ps[i].y+4);
    else Rectangle(dc,
      di->PointList.pl[i].x-4,
      di->PointList.pl[i].y-4,
      di->PointList.pl[i].x+4,
      di->PointList.pl[i].y+4);
   }
   RestoreDC(dc,-1);
  }
 }
 ed->h=TreeView_GetNextSibling(hContent,ed->h);
 return TRUE;
}

// Größten gemeinsamen Teiler finden, l und h müssen positiv sein
int gcd(int l, int h) {
 int t;
 if (l>h) t=h, h=l, l=t;
 while (t=h%l) h=l, l=t;
 return l;
}

// Bruch kürzen
void kuerzen(long&a,long&b) {
 int t=gcd(a,b);
 a/=t; b/=t;
}

struct WEVE{
 int mm;		// Mapping-Mode
 SIZE we,ve;		// WindowExt, ViewportExt
 inline void Set(const cRECT*);	// Bearbeitet die Variablen, benötigt Client-Rechteck
 inline void Out(HDC) const;	// Setzt Mapping-Modus und Extents
private: void ModForWidth();	// modifiziert für 1-Rollbalken-Variante
};

void WEVE::ModForWidth() {
 int y=MulDiv(we.cx, ve.cy*dpi.y*scr.x, ve.cx*dpi.x*scr.y);
 if (y<=we.cy) we.cy=y;
 else we.cx=MulDiv(we.cy, ve.cx*dpi.x*scr.y, ve.cy*dpi.y*scr.x);
}

void WEVE::Set(const cRECT*r) {
 mm=MM_ISOTROPIC;
 if (CurZoom>0) {
  we.cx=dpi.x*1000;
  we.cy=dpi.y*1000;
  ve.cx=scr.x*CurZoom;
  ve.cy=scr.y*CurZoom;
  kuerzen(we.cx,ve.cx);	// Überläufe im GDI vermeiden
  kuerzen(we.cy,ve.cy);
 }else{
  ve.cx=r->Width();
  ve.cy=r->Height();
  switch (CurZoom) {
   case ZOOM_BBOX_A:	mm=MM_ANISOTROPIC;
   case ZOOM_BBOX_W:
   case ZOOM_BBOX:	we.cx=rcBBox.Width();
			we.cy=rcBBox.Height();
			if (CurZoom==ZOOM_BBOX_W) ModForWidth();
			break;
   case ZOOM_FRAME_A:	mm=MM_ANISOTROPIC;
   case ZOOM_FRAME_W:
   case ZOOM_FRAME:	we.cx=rcFrame.Width();
			we.cy=rcFrame.Height();
			if (CurZoom==ZOOM_FRAME_W) ModForWidth();
			break;
   case ZOOM_TEXT:	mm=MM_TEXT; break;
  }
 }
}

void WEVE::Out(HDC dc) const{
 SetMapMode(dc,mm);
 SetWindowExtEx(dc,we.cx,we.cy,NULL);
 SetViewportExtEx(dc,ve.cx,ve.cy,NULL);
}

// Skalierung setzen, aber keine Offsets
static HDC ScaleDC(HWND Wnd, HDC dc=0) {
 if (!dc) dc=GetDC(Wnd);
 WEVE weve;
 cRECT r;
 GetClientRect(Wnd,&r);
 weve.Set(&r);
 weve.Out(dc);
 return dc;
}

// Skalierung und Ursprung setzen
static HDC SetupDC(HWND Wnd, HDC dc=0) {
 dc=ScaleDC(Wnd,dc);
 OffsetDC(Wnd,dc);
 return dc;
}

static void GetZoom(HDC dc, POINT*z) {	// liefert Zoom in X- und Y-Richtung
 SIZE we,ve;
 GetWindowExtEx(dc,&we);
 GetViewportExtEx(dc,&ve);
 z->x=MulDiv(1000,ve.cx*dpi.x,we.cx*scr.x);
 z->y=MulDiv(1000,ve.cy*dpi.y,we.cy*scr.y);
}

static int GetZoom(HDC dc) {		// liefert mittleren Zoom
 POINT z;
 GetZoom(dc,&z);
 return (z.x+z.y)>>1;
}

// vergrößern/verkleinern in <dir> Schritten entsprechend <ZoomTab> (= vorgegebene Festwerte = Stufen),
// liefert geeignete Vergrößerung oder 0 bei Fehler
static int NextZoom(HWND Wnd, int dir) {
 static const int ZoomTab[]={10,   15,   20,   30,   50,   70,
			     100,  150,  200,  300,  500,  700,
			     1000, 1500, 2000, 3000, 5000, 7000,
			     10000,15000,20000,30000,50000,70000,
			     100000};
 if (!dir) return 0;	// keine Änderung
 HDC dc=ScaleDC(Wnd);
 int z=GetZoom(dc);
 ReleaseDC(Wnd,dc);
 int i;
 for (i=0; i<elemof(ZoomTab); i++) if (z<=ZoomTab[i]) break;	// in Tabelle finden
// Der Index zeigt auf die aktuelle oder nächstgrößere Zoomstufe
 if (dir>=0 && z!=ZoomTab[i]) i--;	// auf die nächstkleinere Zoomstufe setzen
 if (!i && dir<0) return 0;		// Zoom bereits <= 10%, kann nicht kleiner!
 if (z>=100000 && dir>=0) return 0;	// Zoom bereits >= 10000%, kann nicht größer!
 i+=dir;
 if (i<0) i=0;
 if (i>elemof(ZoomTab)-1) i=elemof(ZoomTab)-1;	// eingrenzen
 return ZoomTab[i];
}

// Numerischen Zoom in Statuszeile anzeigen
// Der DC-Parameter muss mit ScaleDC() initialisiert worden sein.
static void ShowZoom(HDC dc) {
 TCHAR s[64];
 POINT z;
 GetZoom(dc,&z);
 s[_sntprintf(s,elemof(s)-1,z.x!=z.y?T("Zoom: %g/%g %%"):T("Zoom: %g %%"),z.x*0.1,z.y*0.1)]=0;
 SendMessage(hStatus,SB_SETTEXT,0,(LPARAM)s);
}

// MatchPos[0] enthält Mausposition in Client-Koordinaten
// MatchPos[1] enthält Mausposition in logischen Koordinaten
// Als unechter Zeiger (=1) wird nur Zoom-Änderung angezeigt (ohne Positionsfestlegung)
static void SetupScrollbars(HWND Wnd, POINT MatchPos[2]=(POINT*)1) {
 RECT r;	// Neue Bildgröße in Bildschirmpixel (nur bei ändernder Vergrößerung)
 if (MatchPos) {
  HDC dc=ScaleDC(Wnd);
  ShowZoom(dc);
  IntersectRect(&r,&rcBBox,&rcFrame);
  LPtoDP(dc,(POINT*)&r,2);	// Die Rollbalken führen Device-Koordinaten!
  if ((UINT_PTR)MatchPos>1) LPtoDP(dc,MatchPos+1,1);	// Pixel-Koordinaten
  ReleaseDC(Wnd,dc);
 }
 RECT rc;
 GetClientRect(Wnd,&rc);
 SCROLLINFO si;
 si.cbSize=sizeof(si);
 si.fMask=SIF_RANGE|SIF_PAGE|SIF_POS;
 GetScrollInfo(Wnd,SB_HORZ,&si);
 si.nPos+=(int)(si.nPage-rc.right)>>1;	// Bild zentrieren
 si.nPage=rc.right;
 if (MatchPos) {
  if ((UINT_PTR)MatchPos>1) si.nPos=MatchPos[1].x-MatchPos[0].x;
  si.nMin=r.left;
  si.nMax=r.right-1;
 }
 SetScrollInfo(Wnd,SB_HORZ,&si,TRUE);
 GetScrollInfo(Wnd,SB_VERT,&si);
 si.nPos+=(int)(si.nPage-rc.bottom)>>1;
 si.nPage=rc.bottom;
 if (MatchPos) {
  if ((UINT_PTR)MatchPos>1) si.nPos=MatchPos[1].y-MatchPos[0].y;
  si.nMin=r.top;
  si.nMax=r.bottom-1;
 }
 SetScrollInfo(Wnd,SB_VERT,&si,TRUE);
}

static void HandleWmSize(HWND Wnd) {
 static BYTE InHandler;	// Endlose Verschachtelungen können durch zu- und abschaltende Rollbalken entstehen!
 if (InHandler<2) {	// Maximal 2 Iterationen zulassen
  InHandler++;
  SetupScrollbars(Wnd,(POINT*)(CurZoom<0));
  InHandler--;
 }
}

// Zoomstufe ändern mit Mausposition in Client-Koordinaten
// Bei Auslösung von Tastatur wird die Bildmitte genommen
bool SetZoom(HWND Wnd, int newzoom) {
 cRECT r;
 GetClientRect(Wnd,&r);
 POINT cpt[2];
  cpt[0].x=r.right>>1;
  cpt[0].y=r.right>>1;		// Center-Point
 if (ZOOM_MOUSEUD-128<=newzoom && newzoom<ZOOM_MOUSEUD+128) {
  DWORD gmp=GetMessagePos();
  cpt[0].x=GET_X_LPARAM(gmp);
  cpt[0].y=GET_Y_LPARAM(gmp);
  ScreenToClient(Wnd,cpt);
  newzoom=NextZoom(Wnd,newzoom-ZOOM_MOUSEUD);
  if (!newzoom) return false;
 }else if (ZOOM_UD-128<=newzoom && newzoom<ZOOM_UD+128) {
  newzoom=NextZoom(Wnd,newzoom-ZOOM_UD);
  if (!newzoom) return false;
 }
 if (newzoom>100000) return false;
 if (newzoom<-6) return false;
 HDC dc=SetupDC(Wnd);
 cpt[1]=cpt[0];
 DPtoLP(dc,cpt+1,1);	// Eine Koordinate umrechnen
 ReleaseDC(Wnd,dc);
 CurZoom=newzoom;
 SetupScrollbars(Wnd,cpt);
 InvalidateRect(Wnd,NULL,TRUE);
 return true;
}

bool CanZoom(HWND Wnd, int newzoom) {
 if (newzoom>100000) return false;
 if (newzoom==ZOOM_UD-1 && CurZoom==10) return false;
 if (newzoom==ZOOM_UD+1 && CurZoom==100000) return false;
 if (newzoom==ZOOM_NEXT || newzoom==ZOOM_PREV) return false;
 return true;
}

EXTERN_C LRESULT CALLBACK ShowProc(HWND Wnd,UINT Msg,WPARAM wParam,LPARAM lParam) {
 static POINT StartDrag;

 switch (Msg) {
  case WM_CREATE: {
   HDC dc=GetDC(Wnd);
   scr.x=GetDeviceCaps(dc,LOGPIXELSX);
   scr.y=GetDeviceCaps(dc,LOGPIXELSY);
   ReleaseDC(Wnd,dc);
//   SetupScrollbars(Wnd);	// setzt Bereich der Scrollbalken
  }break;

  case WM_PAINT: {
   PAINTSTRUCT ps;
   BeginPaint(Wnd,&ps);
   SendMessage(Wnd,WM_PRINTCLIENT,(WPARAM)ps.hdc,0);
   EndPaint(Wnd,&ps);
  }break;

  case WM_PRINTCLIENT: {
   RECT r;
   GetClientRect(Wnd,&r);
   EMFDRAW ed;
   HDC dc=SetupDC(Wnd,(HDC)wParam);
//   SetMapMode(dc,MM_HIMETRIC);
//   SIZE we,ve;
//   GetWindowExtEx(dc,&we);
//   GetViewportExtEx(dc,&ve);
//   debug(("%d %d %d %d",we.cx,we.cy,ve.cx,ve.cy));
//   SetWindowOrgEx(dc,emh.rclFrame.left,emh.rclFrame.top,NULL);
//   SetWindowExtEx(dc,emh.rclFrame.right-emh.rclFrame.left,emh.rclFrame.bottom-emh.rclFrame.top,NULL);
//   SetWindowExtEx(dc,we.cx,we.cy,NULL);


//   SetViewportExtEx(dc,MulDiv(r.right-r.left,zoomtab[zoom],100),MulDiv(r.bottom-r.top,zoomtab[zoom],100),NULL);
//   SetViewportExtEx(dc,round(ve.cx*zoomtab[zoom]),round(-ve.cy*zoomtab[zoom]),NULL);

   Rectangle(dc,rcFrame.left,rcFrame.top,rcFrame.right+1,rcFrame.bottom+1);

   if (pLoadedMeta) {
    if (EmfMode) {
     HENHMETAFILE hMeta;
     hMeta=SetEnhMetaFileBits(lLoadedMeta,pLoadedMeta);
//     PlayEnhMetaFile(dc,hMeta,&rcFrame);
     ed.h=TreeView_GetRoot(hContent);
     EnumEnhMetaFile(dc,hMeta,EmfDrawProc,&ed,&rcFrame);
     DeleteEnhMetaFile(hMeta);
    }else{
     HMETAFILE hMeta;
     LPBYTE pMeta=pLoadedMeta;
     DWORD lMeta=lLoadedMeta;
     PLACEABLE_HEADER *H=(PLACEABLE_HEADER*)pMeta;
//     SetViewportOrgEx((HDC)wParam,r.left,r.top,NULL);
     if (H->id==PLACEABLE_HEADER_ID) {
//      SetMapMode(dc,MM_ANISOTROPIC);
//      SetViewportExtEx(dc,r.right-r.left,r.bottom-r.top,NULL);
//      SetWindowOrgEx(dc,H->rcArea.left,H->rcArea.top,NULL);
//      SetWindowExtEx(dc,H->rcArea.Width(),H->rcArea.Height(),NULL);
      pMeta+=sizeof(PLACEABLE_HEADER);
      lMeta-=sizeof(PLACEABLE_HEADER);
     }
     hMeta=SetMetaFileBitsEx(lMeta,pMeta);
     PlayMetaFile((HDC)wParam,hMeta);
     DeleteMetaFile(hMeta);
    }
   }

//   GetClientRect(Wnd,&r);
//   ENHMETAHEADER *emh=(ENHMETAHEADER*)pLoadedMeta;
//   if (!emh) break;
//   GetEnhMetaFileHeader(Emf,sizeof(emh),&emh);

// Papierseite (Ausdehnung der EMF-Datei)
#if 0
   Rectangle(dc,emh.rclFrame.left,emh.rclFrame.top,emh.rclFrame.right,emh.rclFrame.bottom);
//#else
   POINT pt[]={
    {emh->rclFrame.left,emh->rclFrame.top},
    {emh->rclFrame.right,emh->rclFrame.top},
    {emh->rclFrame.right,emh->rclFrame.bottom},
    {emh->rclFrame.left,emh->rclFrame.bottom}};
   Polygon(dc,pt,elemof(pt));
#endif
// Aufdruck
//   RECT r;
//   SetRect(&r,emh->rclFrame.left,emh->rclFrame.top,emh->rclFrame.right,emh->rclFrame.bottom);
//   r.right=r.left+MulDiv(r.right-r.left,emh->szlDevice.cx,100*emh->szlMillimeters.cx);
//   r.bottom=r.top+MulDiv(r.bottom-r.top,emh->szlDevice.cy,100*emh->szlMillimeters.cy);
//   PlayEnhMetaFile(dc,Emf,&r);
  }break;

  case WM_MOUSEWHEEL: {
   POINT pm={GET_X_LPARAM(lParam),GET_Y_LPARAM(lParam)};
   ScreenToClient(Wnd,&pm);
   if (!SetZoom(Wnd,ZOOM_MOUSEUD+GET_WHEEL_DELTA_WPARAM(wParam)/WHEEL_DELTA))
     MessageBeep(MB_ICONEXCLAMATION);
  }break;

  case WM_CHAR: {
   switch (wParam) {
    case '+': SetZoom(Wnd,ZOOM_UD+1); break;
    case '-': SetZoom(Wnd,ZOOM_UD-1); break;
    case ' ': SetZoom(Wnd,ZOOM_FRAME_A); break;
   }
  }break;

  case WM_MOUSEMOVE: if (wParam&MK_LBUTTON) {
   ScrollWindow(Wnd,
     MoveScrollPos(Wnd,SB_HORZ,GET_X_LPARAM(lParam)-StartDrag.x),
     MoveScrollPos(Wnd,SB_VERT,GET_Y_LPARAM(lParam)-StartDrag.y),NULL,NULL);
   StartDrag.x=GET_X_LPARAM(lParam);
   StartDrag.y=GET_Y_LPARAM(lParam);
  }else{
   POINT p1,p2;
//   GetImageOrg(Wnd,&pt);
   p1.x=GET_X_LPARAM(lParam);
   p1.y=GET_Y_LPARAM(lParam);
   p2=p1;
   HDC dc=SetupDC(Wnd);
   DPtoLP(dc,&p2,1);
   ReleaseDC(Wnd,dc);
//   POINTF p1,p2;
//   ENHMETAHEADER *emh=(ENHMETAHEADER*)pLoadedMeta;
//   if (!emh) break;
//   GetEnhMetaFileHeader(Emf,sizeof(emh),&emh);
//   p1.x=pt.x/zoomtab[zoom]/ScreenRes.x;		// Millimeter in der Vektorgrafik
//   p1.y=pt.y/zoomtab[zoom]/ScreenRes.y;
//   p2.x=p1.x*rcFrame.Width();	// "Pixel" (Rastereinheiten) in der Vektorgrafik
//   p2.y=p1.y*rcFrame.Height();
   TCHAR s[32];
   s[_sntprintf(s,elemof(s)-1,T("%d/%d ScrPix"),p1.x,p1.y)]=0;
   SendMessage(hStatus,SB_SETTEXT,1,(LPARAM)s);
//   s[_sntprintf(s,elemof(s)-1,T("%g/%g mm"),p1.x,p1.y)]=0;
//   SendMessage(hStatus,SB_SETTEXT,2,(LPARAM)s);
   s[_sntprintf(s,elemof(s)-1,T("%d/%d EmfPix"),p2.x,p2.y)]=0;
   SendMessage(hStatus,SB_SETTEXT,3,(LPARAM)s);
  }break;

  case WM_LBUTTONDOWN: {
   SetFocus(Wnd);
   StartDrag.x=GET_X_LPARAM(lParam);
   StartDrag.y=GET_Y_LPARAM(lParam);
   SetCursor(LoadCursor(0,IDC_HAND));
   SetClassLong(Wnd,GCL_HCURSOR,(LONG)LoadCursor(0,IDC_HAND));
  }break;

  case WM_LBUTTONUP: {
   SetCursor(LoadCursor(0,IDC_CROSS));
   SetClassLong(Wnd,GCL_HCURSOR,(LONG)LoadCursor(0,IDC_CROSS));
  }break;

  case WM_NCCALCSIZE: if (wParam && CurZoom>=0) {
   LRESULT ret=DefWindowProc(Wnd,Msg,wParam,lParam);
   static POINT prev;
   POINT size;
   LPNCCALCSIZE_PARAMS csp=(LPNCCALCSIZE_PARAMS)lParam;
   size.x=csp->rgrc[2].right-csp->rgrc[2].left;
   size.y=csp->rgrc[2].bottom-csp->rgrc[2].top;

//   cRECT r;
//   GetClientRect(Wnd,&r);
//   r.left=csp->rgrc[2].right-csp->rgrc[2].left;
//   r.top =csp->rgrc[2].bottom-csp->rgrc[2].top;
   debug(("ClientSize=(%d,%d), rc2Width=(%d,%d)",
     prev.x,
     prev.y,
     size.x,
     size.y));
   prev=size;
   debug(("r1=(%d,%d,%d,%d), r2=(%d,%d,%d,%d)",
    csp->rgrc[1].left,csp->rgrc[1].top,csp->rgrc[1].right,csp->rgrc[1].bottom,
    csp->rgrc[2].left,csp->rgrc[2].top,csp->rgrc[2].right,csp->rgrc[2].bottom));
   POINT co,cn;
   co.x=((cRECT*)(csp->rgrc+2))->MidX();
   co.y=((cRECT*)(csp->rgrc+2))->MidY();
   cn.x=((cRECT*)(csp->rgrc+0))->MidX();
   cn.y=((cRECT*)(csp->rgrc+0))->MidY();
   csp->rgrc[1]=csp->rgrc[0];
   csp->rgrc[1].left+=cn.x-co.x;
   csp->rgrc[1].top +=cn.y-co.y;
   return WVR_VALIDRECTS;
//   return ret;
  }break;

  case WM_SIZE: HandleWmSize(Wnd); break;

  case WM_HSCROLL: HandleWmScroll(Wnd,SB_HORZ,LOWORD(wParam)); break;

  case WM_VSCROLL: HandleWmScroll(Wnd,SB_VERT,LOWORD(wParam)); break;

 }
 return DefWindowProc(Wnd,Msg,wParam,lParam);
}

#if 0
static LPARAM WINAPI MainWndProc(HWND Wnd,UINT Msg,WPARAM wParam,LPARAM lParam) {
 switch (Msg) {
  case WM_NCCREATE: MainWnd=Wnd; break;

  case WM_CREATE: {
// 1 Blatt Papier des Defaultdruckers, in Defaultauflösung (meist 300 dpi)
   PRINTDLG pd={
     sizeof(pd),
     0,
     NULL,
     NULL,
     0,
     PD_RETURNDC|PD_RETURNDEFAULT};
   PrintDlg(&pd);
   DEVMODE*dm=(DEVMODE*)GlobalLock(pd.hDevMode);

   RECT r;
//   SetRect(&r,0,0,8*2540,12*2540);	// Papiergröße 8" x 12" (Leporello)
   SetRect(&r,0,0,dm->dmPaperWidth*10,dm->dmPaperLength*10);
   HDC dc=CreateEnhMetaFile(pd.hDC,NULL,&r,T("spe2\0Papierseite\0"));
   HPEN pen=CreatePen(PS_SOLID,0,0x00F000);
   HPEN open=SelectPen(dc,pen);
   InflateRect(&r,-1000,-1000);
   Rectangle(dc,r.left,r.top,r.right,r.bottom);
   Line(dc,r.left,r.top,r.right,r.bottom);
   Line(dc,r.left,r.bottom,r.right,r.top);
   InflateRect(&r,1000,1000);
   DeletePen(SelectPen(dc,pen=CreatePen(PS_SOLID,0,0xC0C0C0)));
   int i;	//zölliges Raster
   for (i=2540; i<r.right; i+=2540) Line(dc,i,r.top,i,r.bottom);
   for (i=2540; i<r.bottom; i+=2540) Line(dc,r.left,i,r.right,i);
   SelectPen(dc,open);
   DeletePen(pen);
   TCHAR s[32];
//   int l=wsprintf(s,"xy = %d %d",r.right,r.bottom);
//   SelectFont(dc,CreateFont(1000,0,0,0,0,0,0,0,0,0,0,0,0,T("Arial")));
//   TextOut(dc,1500,1500,s,l);
   ESCP escp;
   escp.Init();
   escp.Draw(dc,"serielle_Daten.prn");
   Emf=CloseEnhMetaFile(dc);
   static const int widths[]={100,200,350,500,-1};
   SendMessage(hStatus,SB_SETPARTS,elemof(widths),(LPARAM)widths);
   s[_sntprintf(s,elemof(s)-1,T("%g/%g mm Paper"),dm->dmPaperWidth*0.1F,dm->dmPaperLength*0.1F)]=0;
   SendMessage(hStatus,SB_SETTEXT,4,(LPARAM)s);
   SetFocus(EmfShow);
  }break;

  case WM_SIZE: {
   SendMessage(hStatus,Msg,wParam,lParam);
   RECT r;
   GetWindowRect(hStatus,&r);
   SetWindowPos(EmfShow,0,0,0,GET_X_LPARAM(lParam),GET_Y_LPARAM(lParam)+r.top-r.bottom,SWP_NOZORDER|SWP_NOMOVE);
  }break;

  case WM_DESTROY: {
   DeleteEnhMetaFile(Emf);
   PostQuitMessage(0); 
  }break;

//  case WM_MOUSEWHEEL: {
//   MessageBeep(0);
//  }break;
 }
 return DefWindowProc(Wnd,Msg,wParam,lParam);
}

EXTERN_C void WINAPI WinMainCRTStartup() {
 Inst=GetModuleHandle(NULL);
 InitCommonControls();

 WNDCLASSEX wc={
  sizeof(wc),
  CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS,
  MainWndProc,
  0,0,
  Inst,
  LoadIcon(Inst,MAKEINTRESOURCE(1)),
  0,
  0,
  NULL,
  T("emf"),
  0};
 RegisterClassEx(&wc);

 wc.lpfnWndProc=EmfShowProc;
 wc.hIcon=0;
 wc.hbrBackground=(HBRUSH)(COLOR_APPWORKSPACE+1);
 wc.lpszClassName=T("EmfShow");
 RegisterClassEx(&wc);

 CreateWindowEx(0,T("emf"),T("Testprogramm ESC/P2-Druckerfilter"),WS_OVERLAPPEDWINDOW,
   CW_USEDEFAULT,0,CW_USEDEFAULT,0,
   0,0,Inst,NULL);
 ShowWindow(MainWnd,SW_SHOWDEFAULT);

 MSG Msg;
 while (GetMessage(&Msg,0,0,0)) {
  TranslateMessage(&Msg);
  DispatchMessage(&Msg);
 }
 ExitProcess(Msg.wParam);
}
#endif
Detected encoding: ANSI (CP1252)4
Wrong umlauts? - Assume file is ANSI (CP1252) encoded