/************************************************
* DCF77-Funkuhr-Empfänger über serielles Port *
* oder auch Parallelport (via inpout32.dll) *
* sowie viele andere Eingabemöglichkeiten *
* haftmann#software, Juni 2007 ~ Juni 2013 *
************************************************/
#define _WIN32_IE 0x0501 // Tray-Icon mit Ballon-Hilfe
#define _WIN32_WINNT 0x0500 // 0x0501: Problem mit zu neuem SDK und XP: Fehlende ToolTips unter 9x/2k!
#define NOATOM
#define NOCLIPBOARD
#define NOCRYPT
#define NOGDICAPMASKS
#define NOIME // kein Japanisch <ime.h>
#define NOMCX // kein Modem-Kram <mcx.h>
#define NOMETAFILE
#define NOOPENFILE
#define NOPROFILER
#define NOSOUND
#define NOSYSCOMMANDS
#define NOTEXTMETRIC
#define NOWH
#define WIN32_LEAN_AND_MEAN // schneller compilieren
#include <windows.h>
#include <windowsx.h>
#include <shellapi.h> // notwendig wegen ...
#include <mmsystem.h> // ... WIN32_LEAN_AND_MEAN
#include <shlwapi.h>
#include <commctrl.h>
#include <setupapi.h>
#include <htmlhelp.h>
#include <hidsdi.h>
#include <hidpi.h>
// meine Standard-Definitionen
#define elemof(x) (sizeof(x)/sizeof((x)[0]))
#define T(x) TEXT(x)
#ifndef __cplusplus
typedef enum {false,true} bool;
#endif//__cplusplus
#define nobreak
#ifdef WIN95
# undef StrCatBuff
# define StrCatBuff(d,s,l) lstrcat(d,s)
// IE<5.0 shlwapi enhält kein längenbegrenztes wsprintf!
# undef wvnsprintf
# define wvnsprintf(d,l,t,a) wvsprintf(d,t,a)
# define CancelIo(h)
# define FlashWindowEx(p) FlashWindow((p)->hwnd,(p)->dwFlags);
# define TrackMouseEvent(p)
#endif
#define PI 3.14159265358979323846
#define LN10 2.30258509299404568402
#define LOG2E 1.44269504088896340736
#define PI180 (PI/180)
//#ifndef INT_MIN
//# define INT_MIN (-2147483647 - 1)
//# define INT_MAX 2147483647
//#endif
typedef struct{
short left,top,right,bottom;
}RECTS;
typedef union { // Alles was irgendwie 64 Bits sind
ULONGLONG ull;
LONGLONG ll;
FILETIME ft;
LARGE_INTEGER li;
DWORD dw[2];
WORD w[4];
BYTE b[8];
div_t d;
struct{DWORD Tag,Nacht;};
struct{DWORD Lo,Hi;};
struct{int x,y;};
RECTS rc;
POINT pt;
SIZE sz;
}U64;
/*** Funkuhr.c ***/
extern HINSTANCE ghThisInst; // diese .EXE-Datei
extern HINSTANCE ghInstance; // ggf. Benutzer-Ressourcen
extern NOTIFYICONDATA nid;
#define MainWnd (nid.hWnd)
extern HWND PropWnd;
extern long (WINAPI*Decrypt)(BYTE*);
extern DWORD Cache24[480];
extern TCHAR sDecimal[2]; // Dezimaltrennzeichen (Punkt oder Komma)
extern TCHAR sTime[2]; // Uhrzeit-Trennzeichen (typ. Doppelpunkt)
extern TCHAR sGrad[4]; // Grad-Zeichen (typ. "°", ASCII "grd")
extern TCHAR HelpName[]; // Hilfe-Dateiname (*.hlp, nicht *.chm)
extern TCHAR CacheName[]; // Cache24-Datei (speichert Wetterdaten parallel zur Registrierung)
extern BYTE CmdLineOpt;
extern bool iMeasure; // 0 = metrisch, 1 = zöllig
extern bool ChmHelp; // 0 = keine oder RTF, 1 = CHM aka HTML
extern char TryReOpen; // 2 nach Neustart und WM_POWER (= 3 Versuche), 0 nach Erfolg
extern DWORD WinVer; // GetVersion()
bool SystemTimeToString(const SYSTEMTIME*st,UINT DateFormat,UINT TimeFormat,LPTSTR p,int len);
bool FileTimeToString(const FILETIME*pft,LPTSTR p,int len,UINT DateFormat, UINT TimeFormat, bool ToLocalTime);
U64 GetSystemFileTime(bool bLocal); // aktuelle UTC oder Lokalzeit holen, als 64-Bit-Zeitstempel
void StartWecker(void);
void ComputerUhrStellen(void);
typedef enum {CONFIG=1,CACHE24=2,ALL=3} WHATSAVE;
void SaveConf(HKEY root, WHATSAVE what);
void SaveConfig(WHATSAVE what);
bool AnimYes(void); // true wenn Icon animiert und/oder Sound ausgegeben werden soll
void AnimateTrayIcon(void);
void ShowProperties(void); // muss neu erzeugt werden, wenn sich Parent-Zuordnung ändert
void SetTrayTip(void);
void MakeIcons(void);
void TrayIconVisChanged(void);
void PropRespawn(void);
void PropInsDelSheet(int iTemplate, int iPos); // iTemplate<0 löscht Seite Nr. iPos
void PropAppendSysMenu(void);
void LocateFile(PTSTR buf,PCTSTR name); // Dateiname an verschiedenen Stellen suchen
HINSTANCE MyLoadLibrary(PCTSTR); // versucht die DLL im übergeordneten Verzeichnis zu finden
void DefHelpProc(HWND Wnd, UINT Msg, LPARAM lParam, UINT id);
#ifdef _M_AMD64
#define HOUR2FILETIME(x) ((x)*60*60*10000000LL)
#define DAY2FILETIME(x) ((x)*24*60*60*10000000LL)
#else
// ohne ULONGLONG-Multiplikation auskommen:
#define HOUR2FILETIME(x) (UInt32x32To64((DWORD)(x),0x10C388D)<<11)
#define DAY2FILETIME(x) ((__int64)((DWORD)(x)*0x324A9A7)<<14) // x max. 4
#endif
// Alles persistente zum Schreiben "in einem Rutsch"
typedef struct {
// Fenster
POINTS WinPos;
// Hardware
BYTE Where; // 0(Seriell), 1(Parallel), 2(Soundkarte), 3(Joystick), 4(UsbPrn), 5(Vorlauf)
BYTE SerialNo; // 0..255 für COM1..COM256
BYTE SerialLineIn; // 0=..., 4=RxD
BYTE SerialLineOut; // 0=..., 2=TxD (Stromversorgung)
WORD ParallelAddr; // Basisadresse!
BYTE ParallelLineIn; // Bit 0..2: Bitnummer, Bit 3-7: Adress-Additiv
BYTE ParallelLineOut; // Bit 0..2: Bitnummer, Bit 3-7: Adress-Additiv
// Empfang
BYTE Piep; // 0=aus, 1..10=ein, Lautstärke
BYTE Minuten; // History-Tiefe (Anzahl »Ringe«, 1..10 [=MINU])
// Histogramm
BYTE ZuKurz; // Unterlauf-Wert [ms] (50 ms)
BYTE Trenn; // Entscheider-Zeitwert [ms] (170 ms)
BYTE ZuLang; // Überlauf-Wert [2ms] (270 ms)
BYTE MaxJitter; // erlaubte Schwankung des Sekundenimpulses (100 ms, nicht benutzt)
// Diagnose
BYTE MinuteZurueck; // Anzeige 0=aktuelle bzw. 1..10 = zurückliegende Minute
// Wetter
char Region; // Vorhersageregion 0..89 (90 = eigene Position)
// Stellen
BYTE Checkmarks; // Bit 0 = Uhr stellen beim Programmstart
// Bit 1 = alle xx Stunden
// Bit 2 = wenn Uhr verstellt
// Bit 3 = Datum stellen
// Bit 4 = MsgBox bei über xx Sekunden
// Bit 5 = SYSTEMTIME stellen (sonst LOCALTIME)
// Bit 6 = frei
// Bit 7 = Eigenschaftsfenster vor primärer Wetterkarte (Owner)
BYTE AfterHour; // Stunden: 24, 0 = ständig stellen
BYTE MsgAtDiff; // Sekunden: 2, 0 = immer informieren
BYTE LastActionCode; // Text für letzte Aktion (String-ID)
DWORD LastActionTime; // Zeit letzte Aktion (als FAT-Zeit)
DWORD LastSet; // Uhr zuletzt erfolgreich gestellt
// TrayIcon
BYTE TrayIconVis; // Sichtbarkeit Tray-Icon, 0=immer, 1=bei Empfang, 2=nie
BYTE TrayIconBlink; // soll's blinken?
BYTE TrayIconAus; // Empfänger ausschalten nach Empfang?
// 0 = ausschalten
// 1 = erst aus wenn OK
// 2 = immer ein, aber nicht blinken/piepsen bei „stillem Empfang“
// 3 = immer ein und immer blinken+piepsen
BYTE ActivePropSheet; // Seite im Eigenschaftsfenster (0..9)
// „Geheime“ Einstellungen ohne Dialogelemente
BYTE ToNoSignal; // TimeOut-Wert für Meldung „Kein Signal“ in s (Standard: 5)
BYTE ToRepNoSig; // TimeOut-Wert für Wiederholungsmeldung „Kein Signal“ in s (Standard: 120)
BYTE ToBalloon; // TimeOut-Wert für Meldungen in s (einige werden in Vielfachen angezeigt; Standard: 10)
BYTE ToSilence; // TimeOut-Wert für Übergang in stillen Empfangsmodus in min (Standard: 15)
// Wetter
BYTE cbSort; // Anzeige- und Sortierkriterium (Low- und High-Nibble, Standard: 0)
// Bit 0 = Stadt (statt Region)
// Bit 1 = zusätzlich Nummer
// Bit 2 = zusätzlich Geokoordinaten
// Bit 3 = alternative Wettersymbole, TODO
// Bit 4 = Nach Land vorsortieren
// Bit 6:5 = nicht(0), alphabetisch(1), W->O(2), N->S(3) sortieren
// Bit 7 = umgekehrt sortieren
// Karte
BYTE kShow; // Sichtbarkeit des Karten-Fensters (Standard: 0x51)
// Bit 1:0 SW_HIDE(0), SW_NORMAL(1), SW_SHOWMINIMIZED(2), SW_SHOWMAXIMIZED(3)
// Bit 2 = horizontaler Rollbalken
// Bit 3 = vertikaler Rollbalken
// Bit 4 = Menüzeile
// Bit 5 = Toolbar (** zwingt Karte in Kindfenster wenn Bit 3:2 gesetzt)
// Bit 6 = Statuszeile (**)
// Bit 7 = Tooltips
char kMini; // Sichtbarkeit und Anordnung des Miniaturfensters (Standard: 0)
// Bit 1:0 = unsichtbar(0), gleitend(1), außen angedockt(2), innen angedockt(3)
// Bit 3:2 = LinksOben(0), RechtsOben(1), LinksUnten(2), RechtsUnten(3)
// Bit 4 = Nur bei Bedarf
// Bit 7:5 = Relative Verkleinerung zum Bildschirm, etwa logarithmisch gestuft
// -4 = 1/4 -3 = 1/6 -2 = 1/8 -1 = 1/12
// ±0 = 1/16(normal)1 = 1/24 +2 = 1/32 +3 = 1/48
// FIXME: Größe schließt/öffnet Fenster, Scrollrad irreführend
BYTE kVis; // Sichtbare Items der Kartendarstellung (Reihenfolge ist fest, Standard: 0x3F)
// Bit 0 = Bitmap, von extern geladen
// Bit 1 = Küstenlinien (TODO)
// Bit 2 = Ländergrenzen (TODO)
// Bit 3 = Land eingefärbt (TODO, mit Ländergrenzen verschieden)
// Bit 4 = Gradnetz
// Bit 5 = Vorhersage-Polygone
// Bit 6 = Polygon-Nummern
// Bit 7 = Städte-Namen
RECTS kPos; // Position des Kartenfensters, in Bildschirmkoordinaten (Standard: 0)
POINTS kScrl; // Scroll-Position, bezogen auf Maßstab 1:1 (Standard: 0, Routine zieht zu gültigem Wert)
char kScale; // Karten-Skalierungs-Exponent (Standard: 0 = 1:1)
// Bit 3:0 = Feinstufung 2 ^ 1/16 = 1,0442738 (mit Shift-Taste), davon:
// Bit 3:2 = Sub-Index, normale Scrollrad-Operation
// Bit 7:4 = ganze Binärstufung, 1/256 (2^-8) .. 128 (2^7), eingegrenzt auf 1/16 .. 16
BYTE kAutoScale; // Automatische Skalierung (Standard: 0x50)
// Bit 0 = auf ganze Fensterbreite
// Bit 1 = auf ganze Fensterlänge (zusammen: Minimum beider)
// Bit 2 = Fenstergröße automatisch verändern
// Bit 3 = über Monitorgrenzen hinweg
// Bit 5:4 = Schriftgröße (6-8-10-12 Punkt)
// Bit 7:6 = Wettersymbolgröße (24-32-48-64 Pixel)
BYTE kWetter; // sichtbare Wetter-Symbole (Standard: 1) (**NW = Niederschlagswahrscheinlichkeit)
// Bit 3:0 = nichts(0), Tag(1), TagTemp(2), Nacht(3), NachtTemp(4), Wind(5), NW**(6), Gefahren(7)
// Bit 5:4 = heute(0), morgen(1), übermorgen(2), Tag4(3)
// Bit 6 = Pieps und blinkender Fenstertitel bei Aktualisierung
// Bit 7 = Hot-Tracking der 4-Tages-Vorhersage im DlgWetter je nach Region
// Weitere Konfigurationswerte
char uRegion; // Benutzer-Region (vor allem falls außerhalb einer der 90 Vorhersageregionen)
// 0..89 = gefundene oder manuell gesetzte Region
// -1 wenn kein uPos
POINTS uPos; // Benutzer-Position ("Fähnchen") in Mercator-Koordinaten
// u.a. für die Berechnung von Sonnen- und Mond-Auf- und Untergang
// Hardware II
char iSoundCard; // Nummer der Soundkarte, -1 = WAVE_MAPPER
BYTE iSampleRate; // Abtastrate (8,11.025,16,22.05,32,44.1,48,96,100,192,200,250)
WORD iFiltFreq; // Einstellbare Filterfrequenz in 2 Hz (im NF-Bereich, falls umgesetzt)
char iAFC; // AFC-Frequenzkorrektur in 0,01 Hz, -126..+126
BYTE iDemodTrig; // Demodulator-Steuerbits
// Bit 0 = AFC (sonst umlaufender oder umherspringender Zeiger)
// Bit 1 = Phasendetektor (sonst Amplitudendetektor), erfordert AFC
// Bit 7:2 = AM-Triggerpegel (zum schnelleren Einpegeln beim Programmstart)
BYTE iJoystick; // Nummer des Joysticks
BYTE iJoyButton; // Bit 4:0 = Nummer des Joystick-Knopfes
// Bit 7:5 = Nummer der Achse, die die Zeit in ms liefert, 0 = keine
BYTE iUsbPrn; // Nummer des USB-Paralleldrucker-Konverters
BYTE iUsbInput; // Verwendeter Eingang (Bitnummer, also 3..5)
BYTE iUsbHid; // Nummer des Vorlaufempfängers
BYTE pedantic; // steuert Fehlerprüfung beim Auswerten der Alarm- und Wetterinformation
// Bit 0 = prüfe Empfang.Okay[minute+0], Länge je nach Bit 3
// Bit 1 = prüfe Empfang.Okay[minute+1], Länge je nach Bit 4
// Bit 2 = prüfe Empfang.Okay[minute+2], Länge 15 Bits
// Bit 3 = prüfe volle Empfangslänge bei minute+0, sonst nur 15 Bits
// Bit 4 = prüfe volle Empfangslänge bei minute+1, sonst 29 Bits (*)
// Bit 5 = prüfe Uhrzeit bei minute+0
// Bit 6 = prüfe vollständige Uhrzeit bei minute+1, sonst nur Minutenangabe
// Bit 5 und Bit 6 gemeinsam prüft auf 1-Minute-Differenz
// Bit 7 = erlaube Fehlerkorrektur
// (*) Bei Wetter-Dekodierung wird Bit 4 und 6 als gesetzt angenommen
// Volle Empfangslänge = 59 Bits;
// 58 Bits genügen wenn Schaltsekunde-Bit gesetzt UND Minute == 0 ist
POINTS kMiniPos; // Position des freien Miniaturfensters, in Pixel relativ zu kPos
}TConfig;
typedef union{ // Alle Prozessoren haben kürzeren Kode beim Zugriff auf Byte-Werte
SYSTEMTIME st;
struct{
BYTE bYear,rsv0;
BYTE bMonth,rsv1;
BYTE bDayOfWeek,rsv2;
BYTE bDay,rsv3;
BYTE bHour,rsv4;
BYTE bMinute,rsv5;
BYTE bSecond,rsv6;
WORD wMilliseconds;
};
}MYSYSTEMTIME;
#define MINU 10 // Anzahl Minuten in Rückverfolgung
// Alle Lesedaten zusammengefasst
typedef struct{ // R/W/- = Asynchroner UhrThread-Zugriff (dort ist kein Schreibzugriff)
bool Signal; // - <true> wenn Trägerabsenkung
bool Luecke; // - <true> wenn "fehlendes" Bit detektiert wurde, dann "Sek" gültig
bool Invers; // R Invertierung entdeckt
bool IntrOK; // R DSR-Wechsel-"Interrupt" klappt (kein 10-ms-Timer)
bool SelfTimeChange; // - WM_TIMECHANGE von eigenem Programm, oder von außen?
BYTE Ein; // R Thread-Zustand:
// 0 = Thread AUS
// 1 = Thread EIN, Empfang TimeOut (> 15 Minuten)
// 2 = Thread EIN, Empfang nach OK (kein Stellen der Uhr mehr)
// 3 = Thread EIN, erste 15 Minuten
bool DauerPiep; // R <true> bei Dauerpieps (Maus zieht an TrackBar)
MYSYSTEMTIME Dek; // - Dekodiertes Datum/Uhrzeit (Icon-Anzeige und Tooltip) - ohne gepatchtes Datum
BYTE Index; // - Aktuelles Telegramm "in Füllung"
BYTE Anzahl; // - Gefüllte Telegramme (mit "Wrap-Around"), das aktuelle nur bis "Sek"
BYTE LastOK; // - Anzahl zusammenhängend OK empfangener Minuten (noch ohne Test der Aufeinanderfolge)
BYTE Sek; // - Impuls-Index
ULONGLONG Data[MINU]; // - regulär 59 Bits, mit Okay=0: Data=0: Ende, Data=1: Fehler
ULONGLONG Okay[MINU]; // - 0: Ende oder Fehler, 1: Datenbit OK
WORD Histo[50]; // - Impulslängen in 10-ms-Schritten, letzter Index für >=490 ms
U64 ZeitAlt; // - Computer-Uhr VOR dem Stellen
U64 ZeitNeu; // - Stell-Zeit für Computer-Uhr (zur Differenz-Ausgabe) - ggf. mit gepatchtem Datum
}TEmpfang;
typedef struct{ // in (mehreren) Eigenschaftsseiten verwendete GDI-Objekte
HBRUSH brKurz; // Kurzer Impuls: dunkelgelb
HBRUSH brLang; // Langer Impuls: hellgelb
HBRUSH brFehl; // Fehlerhafter Impuls: rot
HPEN peDivi; // Teilerstrich (im Histogramm): blau, gepunktet
HPEN peXor; // Stift für R2_XORPEN-Operationen (schwarz auf grau)
HFONT fnQuer; // große Schrift (Diagramm-Hinterlegung)
HFONT fnKursiv; // Kursivschrift (für Erläuterungen im Hardware-Dialog)
HFONT fnFett; // Fettschrift (für farbliche Hervorhebungen)
HPEN peZgr[2]; // Stift für Zeiger im Icon (3 Pixel dick) (Index 1 für hellen Hintergrund)
HPEN peBlau[2]; // blauer Stift Breite 0 (1 Pixel)
HBRUSH brBlau[2]; // blauer Pinsel (für Dreieck = »Sendemast«)
}TGdiObj; // alles - außer die Wetterdarstellung
extern TConfig Config;
extern TEmpfang Empfang;
extern TGdiObj GdiObj;
#define WM_FUNKRECV (WM_USER+201)
// wParam=0: Impuls-Start
// wParam=1: Impuls-Ende, lParam=Index der Histogramm-Einfügung (0xFF=Signalinversion)
// wParam=2: Simulation 59. Sekunde (konzeptionell komplett fragwürdig!)
// wParam=10:Computer-Uhr gestellt
// wParam=11:Weckzeit geändert
// wParam=12:Empfangszustand (Config.Ein) geändert, lParam=alter Zustand
// wParam=13:LastActionCode geändert
// wParam=14:Veränderliche HID-Daten: Akkuspannung und Chiptemperatur verfügbar, lParam=report (Gefahr!?)
// wParam=16:Neue entschlüsselte Wetterdaten, lParam = Cache24-Index
// wParam=17:Tageswechsel (Lokalzeit)
// wParam=18:Wechsel von Config.Region (Aktualisierung der Karten-Polygone auslösen), lParam=altes Config.Region
// wParam=19:Wechsel von Config.uPos und/oder Config.uRegion, je nach lParam
// 0: Setzen von Config.uPos und Config.uRegion (>=0)
// 1: Setzen von Config.uRegion (>=0)
// 2: Löschen der User-Position, also Config.uRegion=-1
#define WM_SetActivity (WM_USER+204) // wParam=0..3 für neue Aktivität
#define WM_MyPosStaat (WM_USER+205) // wParam=0, lParam=0, Ergebnis=-1..NUMSTAAT-1; nur an Kartenfenster zu senden!
/*** DCF77.c ***/
#define WM_RECV_IQ (WM_USER+202) // wParam=I, lParam=Q
#define WM_TryReOpen (WM_USER+203) // Worker-Thread bittet um seinen Neustart
#define IQSHIFT 14
typedef short fft_t; // Datentyp für FFT: <short> oder <int> (ausprobieren!)
typedef struct {
HWND hShowDemod; // Ziel für PostMessage()
DWORD nBlocks; // Blockzähler (Annahme: dwBufferLength==dwBytesRecorded)
bool NoAGC; // Automatische Schaltschwellenanpassung deaktivieren (wird nicht gespeichert)
BYTE lock;
BYTE DoFFT; // FFT durchführen (statt I/Q-Demodulation anzeigen), mit Countdown-Funktion
BYTE FFT_LenShift; // Anzahl der Spektrallinien
fft_t*FFT_Data; // I/Q-Spektrum (lineare Frequenzachse)
int f; // Frequenz des DDS-Generators, in 1/100 Hz
int at; // Triggerschwelle bei Amplitudendemodulation (positiv, gleitend, Tau ca. 5 s)
int i,q,a,n; // I/Q-Signalstärken, Amplitude (=hypoti(i,q)), Gesamtsignal(Rauschen)
// i,q,a = um IQSHIFT linksgeschoben
}TDemodIQ;
extern TDemodIQ DemodIQ;
extern const GUID GUID_DEVINTERFACE_USBPRINT;
typedef struct{
HANDLE hDev; // Gerätetreiber-Kanal
PHIDP_PREPARSED_DATA pd;//HID-...
HIDP_CAPS caps; // HID-...
}THid;
extern THid gHid; // HID-Thread-Info
void FillHidRep4(HWND Wnd, const THid*Hid, PUCHAR report);
BYTE GetBCD(BYTE data, BYTE min, BYTE max); // liefert 0xFF bei Fehler
BYTE CountLsbBits(ULONG l, BYTE bits); // liefert Anzahl 1-Bits
bool DecodeTime(ULONGLONG ll, MYSYSTEMTIME*st);
void ClearHisto(void);
void OnTimerPulsAuswertung(void);
void OnTimerSek59(void);
void OnSignalChange(bool Signal, DWORD Timestamp);
void SetFiltFreq(int f); // Sinustabelle des I/Q-Demodulators neu berechnen
int Logarithmize(int t, int max);// result = ln(t)*max/LN32K
int hypoti(int x, int y); // Hypotenuse berechnen, Integer-Version
int hypot_lazy(int x, int y); // Faule Hypotenusenabschätzung
void SetTrig(void); // Config.iDemodTrig -> DemodIQ.at, AM-Schaltschwelle von Hand einstellen
void UpdateTrig(void); // DemodIQ.at -> Config.iDemodTrig, AM-Schaltschwelle anzeigen
void zeroOverlapped(OVERLAPPED*o); // Dateiposition ind Internal nullsetzen (alles außer hEvent)
int GetMaxReport(const HIDP_CAPS*caps); // Maximale Reportpuffergröße erfragen
bool GetInputReport(HANDLE hDev, void*buf, int len, OVERLAPPED*o);
void AllocFFTSpace(void);
int FiltFreqHz(int*frac); // Ganze Filterfrequenz sowie Feinverstellung (-50..+50)
bool StartEmpfang(void);
bool RestartEmpfang(void);
void EndeEmpfang(void);
void InfoPropSheet(WPARAM wParam, LPARAM lParam);
bool HidOpen(THid*);
void HidClose(THid*);
/*** Sprechblase.c ***/
BOOL RegisterSprechblase(void);
void Sprechblase(void);
/*** wutils.c ***/
extern TCHAR MBoxTitle[64];
void _fastcall InitStruct(LPVOID p, UINT len);
int vMBox(HWND Wnd, UINT id, UINT style, va_list arglist);
int MBox(HWND Wnd, UINT id, UINT style,...);
PTSTR GetStr(PTSTR start, int n); // n-ten nullterminierten String liefern
#ifdef UNICODE
# define GetStrW GetStr
#else
PWSTR GetStrW(PWSTR start, int n);
#endif
BOOL wndSetText(HWND w, PCTSTR t, ...); // Formatierten Fenstertext setzen
int StripAmpersand(PTSTR s); // &-Zeichen entfernen, liefert String-Länge
int GenerateUniqueHotkey(HMENU hSubMenu, PTSTR buf, int len); // etwas eindeutiges generieren
DWORD ClientToScreenS(HWND w, DWORD pos); // ClientToScreen() mit short-Koordinaten
UINT GetCheckboxGroup(HWND Wnd, UINT u, UINT o);
void SetCheckboxGroup(HWND Wnd, UINT u, UINT o, UINT v);
void EnableDlgItem(HWND Wnd, UINT id, BOOL state);
void ShowDlgItem(HWND Wnd, UINT id, int state);
BOOL CheckMenuRadio(HMENU m, UINT id);
void SetCheckMenuGroup(HMENU m, UINT u, UINT o, UINT v);
UINT GetCheckMenuGroup(HMENU m, UINT u, UINT o);
void EnableMenuGroup(HMENU m, UINT u, UINT o, UINT state);
void SetEditText(HWND Wnd, UINT id, LPTSTR s); // dabei Markierung beibehalten
HWND AttachUpDown(HWND Wnd, UINT id, UINT udid, int min, int max, int cur);
bool GetUpDownInt(HWND Wnd, UINT id, int *val);
bool GetUpDownByte(HWND Wnd, UINT id, BYTE *val);
div_t _fastcall mydiv(int,__int64);
#define udiv(z,n) mydiv(n,z) // n muss positiv sein; liefert stets positiven Rest
#ifdef _M_IX86
__forceinline __int64 llrint(double f) {
__int64 i;
_asm fld f
_asm fistp i
return i;
}
#if _MSC_VER < 1400 // Visual C++ 6
__forceinline char _BitScanForward(DWORD*Index, DWORD v) {
_asm bsf eax,v
_asm mov ecx,Index // ohne ECX einzusauen geht es hier nicht
_asm mov [ecx],eax
_asm setnz al
}
__forceinline char _BitScanReverse(DWORD*Index, DWORD v) {
_asm bsr eax,v
_asm mov ecx,Index
_asm mov [ecx],eax
_asm setnz al
}
__forceinline char _bittest(const void*p, DWORD bitnum) {
_asm mov ecx,p
_asm mov eax,bitnum
_asm bt dword ptr [ecx],eax
_asm setc al
}
__forceinline char _bittestandset(void*p, DWORD bitnum) {
_asm mov ecx,p
_asm mov eax,bitnum
_asm bts dword ptr [ecx],eax
_asm setc al
}
__forceinline char _bittestandclear(void*p, DWORD bitnum) {
_asm mov ecx,p
_asm mov eax,bitnum
_asm btr dword ptr [ecx],eax
_asm setc al
}
__forceinline char _bittestandcomplement(void*p, DWORD bitnum) {
_asm mov ecx,p
_asm mov eax,bitnum
_asm btc dword ptr [ecx],eax
_asm setc al
}
__forceinline void __stosd(DWORD*p, DWORD val, DWORD count) {
_asm mov edi,p
_asm mov eax,val
_asm mov ecx,count
_asm rep stosd
}
__forceinline void __movsw(WORD*d, const WORD*s, DWORD count) {
_asm mov edi,d
_asm mov esi,s
_asm mov ecx,count
_asm rep movsw
}
__forceinline void __movsd(DWORD*d, const DWORD*s, DWORD count) {
_asm mov edi,d
_asm mov esi,s
_asm mov ecx,count
_asm rep movsd
}
#endif
#else
__int64 llrint(double f);
#endif
#define lrint(x) (int)llrint(x)
float hypotf(float,float);
POINT _fastcall sincos(int radius, int deg10);
int sinus(int radius, int sec); // Lookuptabellen-Sinus (unnötig)
BOOL _stdcall Line(HDC dc, int x1, int y1, int x2, int y2);
void InitCritSec(void);
void InitBeep(BYTE negvol);
void StartBeep(void);
void StopBeep(void);
void DoneBeep(void);
typedef struct{
HINSTANCE hLib; // Libname = erster String
FARPROC proc[]; // dynamisches Array aus Funktionszeigern; die Länge ergibt sich aus der Anzahl der
}dynaprocs; // …nullterminierten Strings (doppel-null-terminiert)
bool _fastcall dynaload(dynaprocs*,const char*); // liefert false wenn ein Einsprungpunkt nicht vorhanden
bool IsUserAdmin(void); // wie es der Name sagt
void _fastcall bloat(int*dst, const char*src, int len); // Byte-Array zu Integer-Array (typischerweise Punkte)
#ifdef UNICODE
#define MyLoadStringW(id,buf,len) LoadString(ghInstance,id,buf,len)
#else
int MyLoadStringW(UINT id, PWSTR buf, int len);
#endif
__int64 CalcArea(const POINT *p, int n, POINT *c);
#ifdef _DEBUG
void _cdecl dprintf(const char *s,...);
#define DbgPrintf(x) dprintf x
#define assert(x) if (!(x)) dprintf("%s:%d: assert failed: %s\n",__FILE__,__LINE__,#x)
#else
#define DbgPrintf(x)
#define assert(x) x
#endif
/*** mtDekoder ***/
int AlarmDek(BYTE MinuteZurueck);
// MJD480 = Modifiziertes Julianisches Datum = Tage seit 1.1.1601 00:00 * 480 (3 Minuten)
bool BuildCipher(BYTE MinuteZurueck, BYTE cipher[10], DWORD* MJD480);
int GetT3M(int index, int*j3m);
int GetAge(int index, int*j3m);
void SetCache24Entry(DWORD saveindex, DWORD result);
// Berechnet aus <idx> (0..479):
// LOBYTE(LOWORD(result)) = Tag(0) / Nacht(1)
// HIBYTE(LOWORD(result)) = Zeitraum (2 oder 4)
// LOBYTE(HIWORD(result)) = Vorhersageregion 0..89
// HIBYTE(HIWORD(result)) = Gültigkeitsbereich (0..3)
DWORD IndexToRegion(int idx);
int GetHeuteMJD(bool bLocalTime); // sonst MESZ; Tage seit 1601-1-1-00:00
int Cache24Merge(const DWORD other[480]);
/*** allgemein ***/
#ifdef _M_AMD64
# define DWL_MSGRESULT DWLP_MSGRESULT
# define INPOUTDLL T("inpoutx64.dll")
#else
#undef UInt32x32To64
ULONGLONG _fastcall UInt32x32To64(DWORD x,DWORD y);
# define INPOUTDLL T("inpout32.dll")
#endif
/*** Karte.c ***/
#define NUMSTAAT 47 // Europäische Länder inklusive Zwergstaaten, ohne Kanalinseln
#define WM_FocusRegion (WM_USER+202) // (int)wParam = Region
extern const TCHAR KARTECLASSNAME[];
extern HWND hFirst;
void RegisterKarte(void); // Fensterklasse registrieren
HWND Karte(void); // Fenster zeigen (Knopfdruck)
// - wertet UMSCH aus, um ein weiteres Fenster zu öffnen
// - wertet STRG aus, um die JPG-Datei (statt GIF-Datei) zu laden
// Pixelkoordinaten steigen von West nach Ost und von Nord nach Süd
int GetCityX(BYTE index); // Google-Maps-Karten-Pixel-Koordinaten
int GetCityY(BYTE index); // (als Sortierkriterium ausreichend)
typedef struct{
float X,Y;
}PointF; // wie GDIplus
// Länge und Breite steigt von West nach Ost sowie von Süd nach Nord
PointF GetCityKoord(BYTE index); // in Längen- und Breitengrad
// Gleitkommazahl in String — ohne sprintf() o.ä.
int FloatToStr(float v, int nk, PTSTR s, int len);
/*** DlgWetter.c ***/
extern const BYTE Flaggen[90];
extern const WORD Kennzeichen[NUMSTAAT];
extern const char Vierfarben[NUMSTAAT];
void bloatsym(POINT*d, const char*s, int l);
void SetCurRegion(HWND Wnd, int region); // Hot-Tracking-Region setzen
void CreateSymbGdiHandles(void);
void DeleteSymbGdiHandles(void);
void CalcMondalter(void);
int TagesName(int TagNr, TCHAR *buf, int len, HMENU hSubMenu); // Tag = 0..3
void SetRectC(RECT*r,int cx,int cy,int ex,int ey);
void Measure(HDC dc, U64 v, BYTE typ, RECT*rc); // Größe bestimmen
int GetForecast(int,U64[4]);
int SchwerwetterText(PTSTR s, int slen, bool nacht, U64 v, bool statusbar);
int MkTempStringW(DWORD v, PCWSTR fmt, PWSTR buf, int len);
void ptSymbolTag(HDC,U64);
void ptTempTag(HDC,U64);
void ptSymbolNacht(HDC,U64,int TagNr);
void ptTempNacht(HDC,U64);
void ptNSW(HDC,U64);
void ptWind(HDC,U64);
bool TagNachtWarnung(U64);
void ptWarnung(HDC,U64);
/*** Mondalter.c ***/
PointF geoloc; // für Auf- und Untergangszeit, in Grad
int geotz; // Zeitzone zur Berechnung von Auf- und Untergangszeiten, in Minuten, östlich = negativ
TIME_ZONE_INFORMATION geotzi; // mit entsprechend umgerechneten Umschalt-Tagen
double Mondalter(double JDE);
bool AufUntergang(bool bSonne, double MJD, TCHAR*Auf, TCHAR*Unter); // Zeiten in der Form "xx:xx\0"
// bSonne=false: Mond, true=Sonne, 2=bürgerliche Dämmerung, 3=nautische Dämmerung
BOOL GetTimezoneChangeDate(MYSYSTEMTIME *st); // siehe GetTimeZoneInformation()
void InitTZ(void);
/*** pngload.c ***/ // Funktionen, die nur mit Anwesenheit von Gdiplus funktionieren
HBITMAP pngload(PCTSTR); // lädt PNG-Datei (auch .GIF usw.)
/*** DlgXxx.c ***/
INT_PTR CALLBACK HardwareDlgProc(HWND,UINT,WPARAM,LPARAM);
INT_PTR CALLBACK DiagnoseDlgProc(HWND,UINT,WPARAM,LPARAM);
INT_PTR CALLBACK EmpfangDlgProc(HWND,UINT,WPARAM,LPARAM);
INT_PTR CALLBACK StellenDlgProc(HWND,UINT,WPARAM,LPARAM);
INT_PTR CALLBACK HistogrammDlgProc(HWND,UINT,WPARAM,LPARAM);
INT_PTR CALLBACK TrayIconDlgProc(HWND,UINT,WPARAM,LPARAM);
INT_PTR CALLBACK UeberDlgProc(HWND,UINT,WPARAM,LPARAM);
INT_PTR CALLBACK WetterDlgProc(HWND,UINT,WPARAM,LPARAM);
INT_PTR CALLBACK DemodulatorDlgProc(HWND,UINT,WPARAM,LPARAM);
Vorgefundene Kodierung: UTF-8 | 0
|