Quelltext /~heha/hs/Funkuhr.zip/src/Sprechblase.c

/********************************
 * Projekt: Funkuhr DCF77	*
 * Eine Sprechblase, als Ersatz	*
 * für Win98, Me, NT4		*
 ********************************/

#include "Funkuhr.h"

static HWND BlaseWnd;
static HRGN WndRgn;
static RECT TitleRect, TextRect;
static HICON TitleIcon;
static HFONT TitleFont;	// größer und fett
static HPEN FramePen;	// PS_INSIDEFRAME, sonst geht's nicht

#define ROUNDNESS 16	// Abrundung

// Ermittelt den benötigten Platz für die Texte
// Hier: Aufruf vor Fenstererstellung zur Festlegung von Position und Größe
// Die Position eines »Mundstücks« wird hier nicht ermittelt.
// Dies ist in der Tat ein schwieriges Unterfangen, so das Beispiel bei www.codeproject.com.
// Die Sprechblase wird einfach rechts unten positioniert;
// diese Vereinfachung ist falsch im arabischen und hebräischen Windows.
static void CalcRects(void) {
 static const BYTE images[]={0,(BYTE)IDI_ASTERISK,(BYTE)IDI_EXCLAMATION,(BYTE)IDI_HAND};
 BYTE image;
 HDC dc=GetDC(0);	// Bildschirm
 HFONT of;
 int y;
 TitleFont=CreateFont(16,0,0,0,700,0,0,0,
   DEFAULT_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH,
   T("Arial"));
 image=images[nid.dwInfoFlags&3];
 if (image) // LoadImage() lädt keine 16x16-Bilder unter Win98!
   TitleIcon=LoadIcon(0,MAKEINTRESOURCE(MAKEWORD(image,HIBYTE(IDI_ASTERISK))));
 else TitleIcon=0;
 FramePen=CreatePen(PS_INSIDEFRAME,1,GetSysColor(COLOR_INFOTEXT));
 SetRect(&TitleRect,8,8,108,18);
 if (nid.dwInfoFlags) OffsetRect(&TitleRect,36,0);	// Icon-Platz
 of=SelectFont(dc,TitleFont);
 DrawText(dc,nid.szInfoTitle,-1,&TitleRect,DT_CALCRECT|DT_NOPREFIX|DT_SINGLELINE|DT_EXTERNALLEADING);
 y=TitleRect.bottom;
 if (image && y<40) y=40;
 y+=4;
 SetRect(&TextRect,8,y,max(TitleRect.right,108),y);
 SelectFont(dc,GetStockFont(DEFAULT_GUI_FONT));
 y=DT_CALCRECT|DT_NOPREFIX|DT_EXTERNALLEADING;
 if (!StrChr(nid.szInfo,T('\n'))) y|=DT_WORDBREAK;
 DrawText(dc,nid.szInfo,-1,&TextRect,y);
 SelectFont(dc,of);
 ReleaseDC(0,dc);
}


static LRESULT CALLBACK BlaseWndProc(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam) {
 switch (Msg) {
  case WM_CREATE: {
   RECT r;
   BlaseWnd=Wnd;
   GetClientRect(Wnd,&r);
   WndRgn=CreateRoundRectRgn(0,0,r.right,r.bottom,ROUNDNESS,ROUNDNESS);
   SetWindowRgn(Wnd,WndRgn,FALSE);
   SetTimer(Wnd,1,nid.uTimeout*1000,NULL);	// Fenster verschwindet automatisch
   ShowWindow(Wnd,SW_SHOWNOACTIVATE);		// nicht den Fokus übernehmen
   PostMessage(nid.hWnd,nid.uCallbackMessage,NIN_BALLOONSHOW,0);
  }break;

  case WM_PAINT: {
   PAINTSTRUCT ps;
   RECT r;
   HFONT of;
   BeginPaint(Wnd,&ps);
   GetClientRect(Wnd,&r);
	// Blase mit Rahmen zeichnen (ohne "Mundstück")
   SelectBrush(ps.hdc,GetSysColorBrush(COLOR_INFOBK));
   SelectPen(ps.hdc,FramePen);
   RoundRect(ps.hdc,0,0,r.right-1,r.bottom-1,ROUNDNESS,ROUNDNESS);
	// Icon und Überschrift ausgeben
   if (TitleIcon) DrawIcon(ps.hdc,8,8,TitleIcon);
   SetBkMode(ps.hdc,TRANSPARENT);
   SetTextColor(ps.hdc,GetSysColor(COLOR_INFOTEXT));
   of=SelectFont(ps.hdc,TitleFont);
   DrawText(ps.hdc,nid.szInfoTitle,-1,&TitleRect,DT_NOPREFIX|DT_SINGLELINE);
	// Textkörper ausgeben
   SelectFont(ps.hdc,GetStockFont(DEFAULT_GUI_FONT));
   DrawText(ps.hdc,nid.szInfo,-1,&TextRect,DT_NOPREFIX|DT_WORDBREAK);
   EndPaint(Wnd,&ps);
  }return 0;

  case WM_TIMER:
  case WM_LBUTTONDOWN:
  case WM_RBUTTONDOWN:
   PostMessage(nid.hWnd,nid.uCallbackMessage,nid.uID,
     Msg==WM_TIMER?NIN_BALLOONTIMEOUT:NIN_BALLOONUSERCLICK);
   DestroyWindow(Wnd); break;

  case WM_NCDESTROY: {
   DeleteRgn(WndRgn);
   DeleteFont(TitleFont);
   DeletePen(FramePen);
   BlaseWnd=0;
  }break;
 }
 return DefWindowProc(Wnd,Msg,wParam,lParam);
}

// Registeriert Sprechblasen-Fensterklasse
BOOL RegisterSprechblase(void) {
 WNDCLASSEX wc;
 InitStruct(&wc,sizeof(wc));
 wc.style=CS_BYTEALIGNWINDOW|CS_SAVEBITS;
 wc.lpfnWndProc=BlaseWndProc;
 wc.hInstance=ghInstance;
 wc.hCursor=LoadCursor(0,IDC_ARROW);
 wc.lpszClassName=T("Blase");
 return RegisterClassEx(&wc);
}

// Zeigt eine (nichtmodale) Sprechblase an,
// in der Nähe des System-Tray.
// Die Anzeigedaten kommen vom globalen NOTIFYICONDATA
void Sprechblase(void) {
 int w;

 if (BlaseWnd) {
  PostMessage(nid.hWnd,nid.uCallbackMessage,NIN_BALLOONHIDE,0);
  DestroyWindow(BlaseWnd);
 }
 if (!(nid.uFlags&NIF_INFO)) return;	// nur Sprechblase entfernen

 CalcRects();
 w=max(TitleRect.right,TextRect.right);

 CreateWindowEx(WS_EX_TOPMOST|WS_EX_TOOLWINDOW|WS_EX_NOPARENTNOTIFY,
   T("Blase"),NULL,WS_POPUP,
// Hoffentlich sind die Tray-Icons unten rechts!
// Die Taskleiste kann ja auch oben sein.
// Arabisches Windows hat Tray-Icons links.
   GetSystemMetrics(SM_CXFULLSCREEN)-w-32,
   GetSystemMetrics(SM_CYFULLSCREEN)-TextRect.bottom,
   w+8,TextRect.bottom+8,
   0,0,ghInstance,NULL);
}
Vorgefundene Kodierung: UTF-80