/********************************
* Projekt: Funkuhr DCF77 *
* Utility-Sammlung *
********************************/
#include "Funkuhr.h"
/* aus WUTILS.PAS entstanden */
TCHAR MBoxTitle[64];
void _fastcall InitStruct(LPVOID p, UINT len) {
__stosd(p,0,len>>2);
*(UINT*)p=len;
}
int vMBox(HWND Wnd, UINT id, UINT style, va_list arglist) {
TCHAR buf1[256],buf2[1024];
LoadString(ghInstance,id,buf1,elemof(buf1));
wvnsprintf(buf2,elemof(buf2),buf1,arglist);
return MessageBox(Wnd,buf2,MBoxTitle,style);
}
int MBox(HWND Wnd, UINT id, UINT style,...) {
va_list va;
va_start(va,style);
return vMBox(Wnd,id,style,va);
}
// n-ten nullterminierten String liefern
// Liefert <start> für n=0
PTSTR GetStr(PTSTR start, int n) {
if (n) do start+=lstrlen(start)+1; while(--n);
return start;
}
#ifndef UNICODE
PWSTR GetStrW(PWSTR start, int n) {
if (n) do start+=lstrlenW(start)+1; while(--n);
return start;
}
#endif
#ifdef WIN95
int _cdecl wnsprintf(PTSTR s, int slen, PCTSTR t,...) {
return wvsprintf(s,t,(va_list)(&t+1));
}
#endif
// Formatierten Fenster-Text setzen
BOOL wndSetText(HWND w, PCTSTR t, ...) {
TCHAR s[128];
va_list va;
va_start(va,t);
wvnsprintf(s,elemof(s),t,va);
return SetWindowText(w,s);
}
// Entfernt einzelne & aus Menü- oder Static-String, liefert Ergebnis-Stringlänge
// Entfernt auch alles nach "\t"
int StripAmpersand(PTSTR s) {
PTSTR d=s, a=s;
TCHAR c=0;
do{
if (c=='&') {
*d++=c=*s++; // kopieren ohne zu gucken (bei && nämlich)
}else{
c=*s++; // erst gucken, dann kopieren
if (c=='\t') c=0;
if (c!='&') *d++=c;
}
}while(c); // Aufhören, wenn die terminierende Null kopiert wurde
return (int)(d-1-a);
}
// Entnimmt Hotkey aus Menü- oder Static-String; Großbuchstabe
TCHAR GetHotkey(PCTSTR s) {
TCHAR c;
for(;c=*s++;) if (c=='&') {
c=*s++;
if (c!='&') return (TCHAR)CharUpper((PTSTR)(TBYTE)c); // sonst beim Folgezeichen fortsetzen
}
return c; // Null
}
// Findet eindeutigen Hotkey für den gegebenen String in <buf>
// aus den vorhandenen Menüpunkten von <hSubMenu>
// und verdoppelt alle '&' in <buf> zu '&&'
// Liefert Ergebnis-Stringlänge; 0 bei Fehler
int GenerateUniqueHotkey(HMENU hSubMenu, PTSTR buf, int len) {
TCHAR hot[32]; // sollte reichen
TCHAR *s,c;
// 1. Menüstrings nach deren Horkeys durchsuchen und einsammeln
int i,j,k=GetMenuItemCount(hSubMenu);
for (i=j=0; i<k && j<elemof(hot)-1; i++) {
TCHAR b2[64];
if (GetMenuString(hSubMenu,i,b2,elemof(b2),MF_BYPOSITION)
&& (hot[j]=GetHotkey(b2))) j++;
}
hot[j]=0;
// 2. Geeigneten freien Hotkey suchen (c=Hotkey, j = Index)
if (s=StrDup(buf)) {
for (j=0;c=s[j];j++) {
c=(TCHAR)CharUpper((PTSTR)(TBYTE)c);
if (IsCharAlphaNumeric(c) && !StrChr(hot,c)) break;
}
// 3. Hotkey markieren und vorhandene '&' doppeln
for (i=k=0;c=s[i];i++) {
if ((i==j || c=='&') && len>2) *buf++='&', len--, k++;
if (len>1) *buf++=c, len--, k++;
}
*buf=0;
LocalFree(s);
// Resultierende Länge liefern
return k;
}
return 0; // Fehler, <buf> unverändert
}
// ClientToScreen() mit short-Koordinaten
DWORD ClientToScreenS(HWND w, DWORD pos) {
POINT pt={GET_X_LPARAM(pos),GET_Y_LPARAM(pos)};
ClientToScreen(w,&pt);
return MAKELONG(pt.x,pt.y);
}
// Gruppe von Checkboxen zur Bitmaske abfragen
UINT GetCheckboxGroup(HWND Wnd, UINT u, UINT o) {
UINT v,m;
for (v=0,m=1; u<=o; u++,m+=m) if (IsDlgButtonChecked(Wnd,u)==1) v|=m;
return v;
}
// Gruppe von Checkboxen anhand Bitmaske setzen
void SetCheckboxGroup(HWND Wnd, UINT u, UINT o, UINT v) {
for (; u<=o; u++,v>>=1) CheckDlgButton(Wnd,u,v&1);
}
void EnableDlgItem(HWND Wnd, UINT id, BOOL state) {
Wnd=GetDlgItem(Wnd,id);
if (Wnd) EnableWindow(Wnd,state);
}
void ShowDlgItem(HWND Wnd, UINT id, int state) {
Wnd=GetDlgItem(Wnd,id);
if (Wnd) ShowWindow(Wnd,state);
}
BOOL CheckMenuRadio(HMENU m, UINT id) {
return CheckMenuRadioItem(m,id,id,id,0);
}
// wie Get/SetCheckboxGroup, nur für Menüpunkte, via MF_BYCOMMAND
void SetCheckMenuGroup(HMENU m, UINT u, UINT o, UINT v) {
for (; u<=o; u++,v>>=1) CheckMenuItem(m,u,v&1?MF_CHECKED:MF_UNCHECKED);
}
UINT GetCheckMenuGroup(HMENU me, UINT u, UINT o) {
UINT v,m;
for (v=0,m=1; u<=o; u++,m+=m) if (GetMenuState(me,u,0)&MF_CHECKED) v|=m;
return v;
}
void EnableMenuGroup(HMENU m, UINT u, UINT o, UINT state) {
for (; u<=o; u++) EnableMenuItem(m,u,state);
}
// Sovielwie SetDlgItemText(), jedoch Markierung beibehalten
// id kann -1 sein, dann Wirkung wie SetWindowText()
void SetEditText(HWND Wnd, UINT id, LPTSTR s) {
DWORD SelStart,SelEnd;
if (id!=(UINT)-1) Wnd=GetDlgItem(Wnd,id);
SendMessage(Wnd,EM_GETSEL,(WPARAM)&SelStart,(LPARAM)&SelEnd);
SetWindowText(Wnd,s);
Edit_SetSel(Wnd,SelStart,SelEnd);
}
// Die Mindesthöhe des Editelements scheint 14 Dialogeinheiten zu sein!
// Die Zahl <cur> erscheint automatisch im Editfenster.
HWND AttachUpDown(HWND Wnd, UINT id, UINT udid, int min, int max, int cur) {
HWND w=GetDlgItem(Wnd,id);
#if 1
HWND r=CreateWindowEx(0,UPDOWN_CLASS,NULL, // hier: für 32-Bit-Zahlen
WS_CHILD|WS_VISIBLE|WS_BORDER|UDS_ALIGNRIGHT|UDS_NOTHOUSANDS|UDS_HOTTRACK|UDS_SETBUDDYINT|UDS_ARROWKEYS,
0,0,0,0,Wnd,(HMENU)udid,ghThisInst,NULL);
SetWindowPos(r,w,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE); // Reihenfolge sinnvoll setzen
SendMessage(r,UDM_SETBUDDY,(WPARAM)w,0);
SendMessage(r,UDM_SETRANGE32,min,max);
SendMessage(r,UDM_SETPOS32,0,cur);
return r;
#else
return CreateUpDownControl( // wirklich nur für 16 Bit! (Reicht nicht für Filterfrequenz)
WS_CHILD|WS_VISIBLE|WS_BORDER|UDS_ALIGNRIGHT|UDS_NOTHOUSANDS|UDS_HOTTRACK|UDS_SETBUDDYINT|UDS_ARROWKEYS,
0,0,0,0,Wnd,udid,ghThisInst,w,max,min,cur);
#endif
}
bool GetUpDownInt(HWND Wnd, UINT id, int *val) {
BOOL err;
int i=(int)SendDlgItemMessage(Wnd,id,UDM_GETPOS32,0,(LPARAM)&err);
if (err) return false;
if (val) *val=i;
return true;
}
bool GetUpDownByte(HWND Wnd, UINT id, BYTE *val) {
int i;
if (!GetUpDownInt(Wnd,id,&i)) return false;
if (val) *val=(BYTE)i;
return true;
}
#ifdef _M_IX86
// mangels Laufzeitbibliothek "longlong"-Routinen nachreichen,
// diese erwartet in EDX:EAX das "longlong" und in CL die Schiebeweite
// "_cdecl" notwendig, schaltet Namensgarnierung zurück auf '_'-Präfix
// Int64ShrlMod32 usw. sind weniger effektiv als diese Routinen!
ULONGLONG _declspec(naked) _cdecl _allshl(ULONGLONG ll, BYTE shift) {
_asm{
test cl,32
jnz l1
shld edx,eax,cl
shl eax,cl
ret
l1: mov edx,eax
xor eax,eax
shl edx,cl
ret
}
}
ULONGLONG _declspec(naked) _cdecl _aullshr(ULONGLONG ll, BYTE shift) {
_asm{
test cl,32
jnz l1
shrd eax,edx,cl
shr edx,cl
ret
l1: mov eax,edx
xor edx,edx
shr eax,cl
ret
}
}
LONGLONG _declspec(naked) _cdecl _allshr(LONGLONG ll, BYTE shift) {
_asm{
test cl,32
jnz l1
shrd eax,edx,cl
sar edx,cl
ret
l1: mov eax,edx
xor edx,edx
sar eax,cl
ret
}
}
// hier: Einschränkung, nur für DWORD-Divisor
ULONGLONG _declspec(naked) _cdecl _aulldiv(ULONGLONG z, ULONGLONG n) {
_asm{
mov eax,[esp+8] ;High-Teil Zähler
mov ecx,[esp+12] ;Nenner
xor edx,edx
div ecx ;EAX=Ergebnis, EDX=Rest
push eax
mov eax,[esp+8] ;Low-Teil Zähler
div ecx ;EAX=Ergebnis, EDX=Rest
pop edx ;Rest durch High-Teil ersetzen
ret 16
}
}
// hier: Einschränkung, nur für DWORD-Divisor (und damit Rest)
ULONGLONG _declspec(naked) _cdecl _aullrem(ULONGLONG z, ULONGLONG n) {
_asm{
mov eax,[esp+8] ;High-Teil Zähler
mov ecx,[esp+12] ;Nenner
xor edx,edx
div ecx ;EAX=Ergebnis, EDX=Rest
mov eax,[esp+4] ;Low-Teil Zähler
div ecx ;EAX=Ergebnis, EDX=Rest
xor eax,eax ;Ergebnis löschen
xchg edx,eax ;Rest in Low-Teil
ret 16
}
}
// MSVC macht aus dieser (Nicht-Windows-)Funktion ein _aullmul: unnötig!
ULONGLONG _declspec(naked) _fastcall UInt32x32To64(DWORD x,DWORD y) {
_asm{ xchg ecx,eax
mul edx
ret
}
}
div_t _declspec(naked) _fastcall mydiv(int n, __int64 z) {_asm{
mov eax,[esp+4]
mov edx,[esp+8]
idiv ecx
or edx,edx
jns exi
dec eax
add edx,ecx
exi: ret 8
}}
#pragma intrinsic(sin,cos,tan,log,atan,atan2)
static const short v180=1800;
_declspec(naked) POINT _fastcall sincos(int radius, int deg) {_asm{
push ecx // Radius
push edx // Winkel in Zehntelgrad
fild dword ptr[esp+4] // Radius laden
fild dword ptr[esp] // Winkel laden
fldpi // PI laden
fmul
fidiv [v180] // jetzt st(0) = Winkel im Bogenmaß, st(1) = Radius
fsincos // st(0) = Kosinus, st(1) = Sinus, st(2) = Radius
fmul st,st(2)
fxch st(1) // st(0) = Sinus, st(1) = Kosinus, st(2) = Radius
fmulp st(2),st // st(0) = Kosinus, st(1) = Sinus
fistp dword ptr[esp] // Kosinuswert
fistp dword ptr[esp+4] // Sinuswert
pop eax
pop edx
ret
}}
// tatsächlich so kompliziert!
double _cdecl _CIexp() {
_asm{ fldl2e
fmulp st(1),st // st = f * log2 e
fld st // duplizieren
frndint // st = ganzzahliger Teil (Rundung mathematisch)
fsub st(1),st // st(1) = gebrochener Teil (± 0,5)
fxch st(1)
f2xm1 // st = 2^gebrochener_Teil-1 (f2xm1 kann nur im Intervall ±1 arbeiten!)
fld1
faddp st(1),st // 1 addieren: st = 2^gebrochener_Teil
fscale // st = 2^gebrochener_Teil * 2^ganzzahliger_Teil
fxch st(1)
fstp st // ganzzahligen Teil entfernen
}
}
double _cdecl _CIfmod() {
_asm{ fxch st(1)
fprem
fxch st(1)
fstp st(0) // verwerfen
}}
float hypotf(float x, float y) {
_asm{ fld x
fmul st(0),st
fld y
fmul st(0),st
faddp st(1),st
fsqrt
}
}
#endif
char _fltused;
int sinus(int radius, int sec) {
#if 0
// Sinustabelle für ganze Sekunden (6°),
// erster Quadrant, 256=1.0
static const BYTE Sintab[]={
0,27,53,79,104,128,150,171,190,207,222,234,243,250,255};
int quadrant=sec/15;
sec%=15;
if (quadrant&1) sec=15-sec;
if (sec!=15) radius=MulDiv(radius,Sintab[sec],256);
if (quadrant&2) radius=-radius;
return radius;
#else
return sincos(radius,sec*60).y;
#endif
}
BOOL _stdcall Line(HDC dc, int x1, int y1, int x2, int y2) {
#ifdef _M_IX86
return Polyline(dc,(const POINT*)&x1,2); // Parameter liegen auf dem Stack bereits richtig
#else
POINT pt[2]={{x1,y1},{x2,y2}}; // umstapeln
return Polyline(dc,pt,2);
#endif
}
static struct{
// CRITICAL_SECTION CritSec; // BUG: ob CritSec oder hMutex, es hängt mit eingeschaltetem Beep
HANDLE hMutex; // beim Senden von PAUSE an den Dienst ... unerklärlich
HWAVEOUT hWave; // und die Lautstärkeeinstellung funktioniert auch nicht so wie's soll
MMTIME start; // (= geht nicht aus beim Schieben)
WAVEHDR wh[3]; // 3 Indizes für anschwellend, konstant (mit WH_BEGINLOOP und WH_ENDLOOP), abfallend
short buffer[3][60]; // Jeder Puffer benötigt 1,36 ms
}pw; // Piep-Wave
void InitCritSec(void) {
// InitializeCriticalSection(&pw.CritSec);
pw.hMutex=CreateMutex(NULL,FALSE,NULL);
}
static void CalcBuffers(BYTE negvol) {
int i;
for (i=0; i<60; i++) pw.buffer[0][i]=sinus((i<<9)>>negvol,i);
for (i=0; i<60; i++) pw.buffer[1][i]=sinus((120<<8)>>negvol,i);
for (i=0; i<60; i++) pw.buffer[2][i]=sinus(((120<<8)-(i<<9))>>negvol,i);
}
// Sinus (367,5 Hz) auf Soundkarte ausgeben
// mit ansteigender Lautstärke am Anfang und abfallender am Ende
void InitBeep(BYTE negvol) { // negvol=0 (volle Lautstärke) bis 6 (leises Rechteck)
static const WAVEFORMATEX wf={
WAVE_FORMAT_PCM,
1, // Kanäle
22050, // Samples pro Sekunde
44100, // Bytes pro Sekunde
2, // Ausrichtung: WORD
16}; // Bits pro Sample
int i;
if (pw.hWave) {CalcBuffers(negvol); return;} // nur Lautstärke ändern
// EnterCriticalSection(&pw.CritSec);
if (WaitForSingleObject(pw.hMutex,100)) return;
if (!waveOutOpen(&pw.hWave,WAVE_MAPPER,&wf,0,0,0)) {
waveOutPause(pw.hWave);
CalcBuffers(negvol);
for (i=0; i<3; i++) {
WAVEHDR*wh=pw.wh+i;
wh->lpData=(PBYTE)pw.buffer[i];
wh->dwBufferLength=60*2;
wh->dwFlags=i==1?WHDR_BEGINLOOP|WHDR_ENDLOOP:0;
wh->dwLoops=(DWORD)-1;
waveOutPrepareHeader(pw.hWave,wh,sizeof(WAVEHDR));
waveOutWrite(pw.hWave,wh,sizeof(WAVEHDR));
}
pw.start.wType=TIME_SAMPLES;
}
// LeaveCriticalSection(&pw.CritSec);
ReleaseMutex(pw.hMutex);
}
void StartBeep(void) {
int i;
// EnterCriticalSection(&pw.CritSec);
if (WaitForSingleObject(pw.hMutex,100)) return;
if (pw.hWave) {
waveOutPause(pw.hWave);
for (i=0; i<3; i++) {
waveOutWrite(pw.hWave,pw.wh+i,sizeof(WAVEHDR));
}
waveOutGetPosition(pw.hWave,&pw.start,sizeof(pw.start)); // Zeitpunkt vermerken
waveOutRestart(pw.hWave);
}
// LeaveCriticalSection(&pw.CritSec);
ReleaseMutex(pw.hMutex);
}
void StopBeep(void) {
// EnterCriticalSection(&pw.CritSec);
if (WaitForSingleObject(pw.hMutex,100)) return;
if (pw.hWave) {
MMTIME t;
int i=10; // Zähler zur Notbremse (W2k in Nieschütz)
t.wType=TIME_SAMPLES;
do{ // Schneller-Rechner-Problem: Abwarten, bis der mittlere Datenblock an der Reihe ist
waveOutGetPosition(pw.hWave,&t,sizeof(t));
t.u.sample-=pw.start.u.sample;
// if (!t.u.sample) break; // nicht gestartet (waveOutBreakLoop ohne Konsequenz)
if (t.u.sample>60) break; // Mittlerer Block ist erreicht
Sleep(0); // Etwas warten bis zum mittleren Block (Spinlock)
DbgPrintf(("Sleep(0)%d,%d\n",i,t.u.sample));
}while (t.u.sample && --i);
waveOutBreakLoop(pw.hWave);
}
// LeaveCriticalSection(&pw.CritSec);
ReleaseMutex(pw.hMutex);
}
void DoneBeep(void) {
int i;
// EnterCriticalSection(&pw.CritSec);
if (WaitForSingleObject(pw.hMutex,100)) return;
if (pw.hWave) {
waveOutBreakLoop(pw.hWave); // waveOutReset() knackt unangenehm
for (i=0; i<3; i++) {
while (waveOutUnprepareHeader(pw.hWave,pw.wh+i,sizeof(WAVEHDR))) Sleep(0);
}
waveOutClose(pw.hWave);
pw.hWave=0;
}
// LeaveCriticalSection(&pw.CritSec);
ReleaseMutex(pw.hMutex);
}
#ifdef _DEBUG
#if 0//def _M_IX86
// Speicher auf Stack (niemals NULL), len sollte durch 4 teilbar sein!
// Aufrufer muss Standard-Stapelrahmen (mit EBP) haben!
// Diese einfache Routine funktioniert nur mit Alloc-Größen < 4 KByte!
// Ansonsten alloca() aus msvcrt.dll benutzen.
LPVOID _declspec(naked) _fastcall StackAlloc(DWORD len) {
_asm{
pop edx // Rückkehradresse -> EDX
sub esp,ecx // Platz auf Stack
mov eax,esp // Zeiger auf Anfang -> EAX
jmp edx // Rücksprung
}
}
#endif
void _cdecl dprintf(const char *s,...) {
va_list va;
char buf[256];
va_start(va,s);
if (IS_INTRESOURCE(s)) {
char t[256];
LoadStringA(ghInstance,(UINT)s,t,elemof(t));
s=t;
}
wvnsprintfA(buf,elemof(buf),s,va);
OutputDebugStringA(buf);
}
#endif
bool _fastcall dynaload(dynaprocs*dp,const char*e) {
int i;
if (!(dp->hLib=LoadLibraryA(e))) return false;
for (i=0;;i++) {
e+=lstrlenA(e)+1;
if (!*e) return true; // Ende erreicht
if (!(dp->proc[i]=GetProcAddress(dp->hLib,e))) return false;
}
}
// BUG/FEATURE: So wie's ist liefert's FALSE bei abgeschaltetem UAC
bool IsUserAdmin() {
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
PSID AdministratorsGroup;
BOOL b;
#if defined(_M_IX86) && !defined(UNICODE) // dynamische Einsprungpunkte (advapi32.lib) wegen Windows 9x
struct{
HINSTANCE hLib;
BOOL (WINAPI*AllocateAndInitializeSid)(PSID_IDENTIFIER_AUTHORITY,BYTE,
DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,PSID*); // Komisch: Windows98 hat diesen Einsprunkpunkt!
BOOL (WINAPI*CheckTokenMembership)(HANDLE,PSID,PBOOL); // Diesen nicht
BOOL (WINAPI*FreeSid)(PSID); // Diesen hat Win98 wieder
}dp;
static const char names[]="advapi32.dll\0" "AllocateAndInitializeSid\0" "CheckTokenMembership\0" "FreeSid\0";
b=dynaload((dynaprocs*)&dp,names);
FreeLibrary(dp.hLib);
if (!b) return true;
#define DL dp.
#else
#define DL
#endif
b = DL AllocateAndInitializeSid(&NtAuthority, // liefert so unter Win98 FALSE
2,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0,
&AdministratorsGroup);
if (b) {
if (!DL CheckTokenMembership(NULL, AdministratorsGroup, &b)) b = false;
DL FreeSid(AdministratorsGroup);
}
return b;
#undef DL
}
// Byte-Array zu Integer-Array (typischerweise Punkte)
void _fastcall bloat(int*dst, const char*src, int len) {
do *dst++=*src++; while(--len);
}
#ifndef UNICODE
// Unicode-String bei ANSI-Version laden
int MyLoadStringW(UINT id, PWSTR buf, int len) {
HRSRC r=FindResource(ghInstance,MAKEINTRESOURCE((id>>4)+1),RT_STRING);
PCWSTR p=(PCWSTR)LoadResource(ghInstance,r);
if (!p) return 0;
for (id&=15; id; id--) {
p+=*p+1;
}
len--;
if (len<0) return *p+1; // Allokationsgröße in Zeichen
if (len>*p) len=*p;
p++;
__movsw(buf,p,len); // inklusive etwaiger Nullen!
buf[len]=0;
return len;
}
#endif
/**********************************************
* Fläche und Flächenschwerpunkt (Wikipedia):
* A = 1/2 * Summe(x[i]*y[i+1]-x[i+1]*y[i])
* schwer.x = 1/6/A * Summe((x[i]+x[i+1])*(x[i]*y[i+1]-x[i+1]*y[i]))
* schwer.y = 1/6/A * Summe((y[i]+y[i+1])*(x[i]*y[i+1]-x[i+1]*y[i]))
**********************************************/
// liefert Flächeninhalt (in Quadratpixel) und ggf. Schwerpunkt in <*c>
// Nur für Win9x-gängige Polygone mit 16-Bit-Koordinaten!
// (Schwerpunkt == Centroid)
__int64 CalcArea(const POINT *p, int n, POINT *c) {
int i;
int a=0;
int x=0,y=0; // Schwerpunkt
for (i=0;i<n;i++) {
int j=(i+1)%n; // Folgeindex
int t=p[i].x*p[j].y-p[j].x*p[i].y; // gemeinsamer Term: doppelte Dreiecksfläche
a+=t; // Fläche summieren
if (c) {
x+=(p[i].x+p[j].x)*t; // Schwerpunkt jedes Dreiecks mit Flächeninhalt wichten
y+=(p[i].y+p[j].y)*t; // und summieren (in etwa)
}
}
a>>=1; // runden nach –Inf: negativ bleibt negativ
if (c&&a) {
c->x=(x/(3*a))>>1; // gleichfalls nach –Inf runden
c->y=(y/(3*a))>>1; // Bei n=0 <*c> nicht setzen
}
return a;
}
/*
case 0x31A/*WM_THEMECHANGED* /: {
HTHEME th=0;
struct{
HINSTANCE hLib;
HTHEME (WINAPI*GetWindowTheme)(HWND);
}ux;
static const char names[]="uxtheme.dll\0" "GetWindowTheme\0"
if (dynaload((dynaprocs*)&ux,names)) {
th=ux.GetWindowTheme(GetDlgItem(Wnd,16));
}
if (ux.hLib) FreeLibrary(ux.hLib);
di.BrushIndex=th?COLOR_3DHILIGHT:COLOR_3DFACE;
}break;
*/
Vorgefundene Kodierung: ANSI (CP1252) | 4
|
|