/********************************
* 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-8 | 0
|