/********************************
* Projekt: Funkuhr DCF77 *
* Eigenschaftsseite äHardwareô *
* Auswahl serielles oder *
* Parallelport + Leitung *
********************************/
#include "Funkuhr.h"
#include <devguid.h>
//#include <dbt.h>
/*
// Eine Reihe aufeinanderfolgender Fenster ein- oder ausschalten
static void EnableWindows(HWND Wnd, UINT count, BOOL state) {
for (; count; Wnd=GetNextSibling(Wnd),count--) {
EnableWindow(Wnd,state);
}
}
*/
// Je nach Config.Where Dialogelemente sichtbar machen
static void ShowWhere(HWND Wnd) {
int i;
for (i=0; i<6; i++) {
int j=i*0x10+0x20;
int k;
HWND w;
for (w=GetDlgItem(Wnd,j); w && ((k=(short)GetDlgCtrlID(w))==-1 || k<j+0x10); w=GetNextSibling(w)) {
ShowWindow(w,Config.Where==i ? SW_SHOW : SW_HIDE);
}
}
}
#ifdef UNICODE
int ComboBox_AddStringA(HWND Wnd, const char*s) {
TCHAR buf[64];
MultiByteToWideChar(CP_ACP,0,s,-1,buf,elemof(buf));
return ComboBox_AddString(Wnd,buf);
}
#else
# define ComboBox_AddStringA ComboBox_AddString
#endif
// Hilfsfunktion: Fⁿllt Combobox mit doppelnullterminierter Item-Liste
static void cbFillA(HWND Wnd,const char*Items,int CurSel) {
for(;*Items;Items+=lstrlenA(Items)+1) ComboBox_AddStringA(Wnd,Items);
ComboBox_SetCurSel(Wnd,CurSel);
}
// Hilfsfunktion: Formatierte Textzeile hinzufⁿgen
// Wenn t==NULL dann 1 uninterpretierten String-Parameter annehmen
// Wenn t<65536 dann t = String-Resource-ID
// Liefert true wenn itemdata==curitem (um weitere Aktionen zu starten)
static bool cbAddItem(HWND cb, int itemdata, int curitem, PCTSTR t, ...) {
int idx;
va_list va;
va_start(va,t);
if (t) {
TCHAR s[64];
if (IS_INTRESOURCE(t)) {
TCHAR r[64];
LoadString(ghInstance,(UINT)t,r,elemof(r));
t=r;
}
wvnsprintf(s,elemof(s),t,va);
t=s;
}else t=va_arg(va,PCTSTR);
idx=ComboBox_AddString(cb,t);
ComboBox_SetItemData(cb,idx,itemdata);
if (itemdata==curitem) {
ComboBox_SetCurSel(cb,idx);
return true;
}
return false;
}
static const WORD DefAddrs[]={0x378,0x278,0x3BC,0x201};
// Fⁿllt Combobox mit typischen Parallelportadressen
static void cbFillAddrs(HWND Wnd) {
int i;
bool set=false;
for (i=0; i<elemof(DefAddrs); i++) {
if (cbAddItem(Wnd,DefAddrs[i],Config.ParallelAddr,
i<3 ? T("%Xh (%u, LPT%u)") : MAKEINTRESOURCE(11), // "%Xh (Joystick)"
DefAddrs[i],DefAddrs[i],i+1)) set=true;
}
if (!set) wndSetText(Wnd,T("%03Xh"),Config.ParallelAddr);
}
// Fⁿllt Combobox mit Parallelport-Bits
static void cbFillBits(HWND Wnd, BYTE Current) {
static const char ParallelLines[]= // ab Bitadresse 0
"D0 (2)\0D1 (3)\0D2 (4)\0D3 (5)\0D4 (6)\0D5 (7)\0D6 (8)\0D7 (9)\0"
"ERR (15)\0ONL (13)\0PE (12)\0ACK (10)\0BSY (11)\0"
"STB (1)\0AF (14)\0INI (16)\0SEL (17)\0";
static const char JoystickLines[]= // ab Bitadresse 4, nur EingΣnge
"TA1 (2)\0TA2 (7)\0TB1 (10)\0TB2 (14)\0";
int i,j;
const char *p;
ComboBox_ResetContent(Wnd);
if (Current&0x80) { // UsbPrn-Modus
p=ParallelLines;
for (i=0; i<11; i++) {
if (i>=8) ComboBox_AddStringA(Wnd,p);
p+=lstrlenA(p)+1;
}
ComboBox_SetCurSel(Wnd,Current-0x80-013);
}else{ // InpOut32-Modus
for (i=0; i<elemof(DefAddrs); i++) {
if (Config.ParallelAddr==DefAddrs[i]) {
i= i==3 ? 4 : 0; // Start-Bitadresse
p= i ? JoystickLines : ParallelLines;
if (i && !Current) { // Sonderfall Jostick-Stromversorgung
ComboBox_AddStringA(Wnd,"Ucc (1,8,9,15)");
ComboBox_SetCurSel(Wnd,0);
return;
}
for(;*p;p+=lstrlenA(p)+1) {
j=ComboBox_AddStringA(Wnd,p);
ComboBox_SetItemData(Wnd,j,i); // Bitnummer zuordnen
if (i==Current) ComboBox_SetCurSel(Wnd,j);
i++; if (i==8) i+=3; // nΣchstes Bit, 3 fehlende IN-Leitungen ⁿberspringen
}
return;
}
}
for (i=0; i<8; i++) cbAddItem(Wnd,i,Current,T("Bit %u"),i);
}
}
// Wenn die Parallelport-Adresse verΣndert wurde,
// FALSE bei falscher Angabe
static bool OnParallelAddrChange(HWND Wnd) {
TCHAR buf[16];
int a;
buf[0]='0';
buf[1]='x';
GetDlgItemText(Wnd,0x31,buf+2,elemof(buf)-2);
if (!StrToIntEx(buf,STIF_SUPPORT_HEX,&a)) return false;
if (HIWORD(a)) return false; // >FFFFh
if (!HIBYTE(a)) return false; // <100h
if (Config.ParallelAddr==(WORD)a) return true; // unverΣndert
Config.ParallelAddr=(WORD)a; // zuweisen
if (Config.ParallelAddr==DefAddrs[3]) { // Sonderfall Joystick
if (Config.ParallelLineIn<4) Config.ParallelLineIn=4;
Config.ParallelLineOut=0;
}
cbFillBits(GetDlgItem(Wnd,0x32),Config.ParallelLineIn);
cbFillBits(GetDlgItem(Wnd,0x33),Config.ParallelLineOut);
RestartEmpfang();
return true;
}
static void PrepareRedString(HWND Wnd) {
TCHAR t[64];
GetWindowText(Wnd,t,elemof(t)); // Template mit %s laden
wndSetText(Wnd,t,INPOUTDLL);
SendMessage(Wnd,WM_SETFONT,(WPARAM)GdiObj.fnFett,FALSE);
}
// Bei Auswahl einer Soundkarte à
static void FillSamplerates(HWND Wnd) {
WAVEINCAPS wc;
static const int PossibleRates[]={8000,11025,16000,22050,32000,44100,48000,96000,192000,200000};
if (!waveInGetDevCaps(Config.iSoundCard,&wc,sizeof wc)) {
HWND w=GetDlgItem(Wnd,0x42);
WAVEFORMATEX wf;
int j,r=Config.iSampleRate*1000;
ComboBox_ResetContent(w);
// for (j=0; j<elemof(PossibleRates); j++) {
// if (Config.iSampleRate==PossibleRates[j]/1000) r=PossibleRates[j];
// }
wndSetText(w,T("%d"),r);
wf.wFormatTag=WAVE_FORMAT_PCM;
wf.nChannels=1;
wf.wBitsPerSample=16;
wf.nBlockAlign=2;
for (j=0; j<elemof(PossibleRates); j++) {
wf.nSamplesPerSec=PossibleRates[j];
wf.nAvgBytesPerSec=wf.nSamplesPerSec*wf.nBlockAlign;
if (!waveInOpen(NULL,Config.iSoundCard,&wf,0,0,WAVE_FORMAT_QUERY)) {
cbAddItem(w,wf.nSamplesPerSec/1000,Config.iSampleRate,T("%d"),wf.nSamplesPerSec);
}
}
}
}
// Bei Auswahl eines Joysticks à
static void FillButtons(HWND Wnd) {
JOYCAPS jc;
if (!joyGetDevCaps(Config.iJoystick,&jc,sizeof jc)) {
TCHAR s[64],*p=s;
HWND w=GetDlgItem(Wnd,0x52);
int j;
ComboBox_ResetContent(w);
for (j=0; j<(int)jc.wNumButtons; j++) {
cbAddItem(w,j,Config.iJoyButton&0x1F,T("%d"),j+1); // sind unter Windows 1-basiert
}
//verwirrt! EnableWindow(w,jc.wNumButtons>1);
LoadString(ghInstance,21,s,elemof(s));
w=GetDlgItem(Wnd,0x53);
ComboBox_ResetContent(w);
for (j=0; j<8; j++) {
if (j<3 && j<=(int)jc.wNumAxes || j>=3 && jc.wCaps&1<<(j-3)) // ab JOYCAPS_HASZ
cbAddItem(w,j,Config.iJoyButton>>5,NULL,p);
p+=lstrlen(p)+1;
}
EnableWindow(w,jc.wNumAxes);
}
}
static void cbFillFromStringId(HWND Wnd, UINT id) {
TCHAR buf[256], *p=buf;
buf[LoadString(ghInstance,id,buf,elemof(buf)-1)+1]=0; // doppelnullterminiert
for(;*p;p+=lstrlen(p)+1) ComboBox_AddString(Wnd,p);
}
static void SetValue3Decimals(HWND Wnd, UINT id, long v) {
int i,k;
TCHAR s[16];
i=wnsprintf(s,elemof(s)-1,T("%04d"),v)-3; // Fⁿhrende Nullen erzeugen
k=4; do s[i+k]=s[i+k-1]; while(--k); // 3 Nachkommastellen und '\0' schieben
s[i]=sDecimal[0]; // Dezimaltrenner einfⁿgen
SetDlgItemText(Wnd,id,s);
}
// Zeigt Akku-Istspannung und Chiptemperatur
void FillHidRep4(HWND Wnd, const THid*Hid, PUCHAR report) {
long v;
HidP_GetScaledUsageValue(HidP_Input,0x84,0,0x30,&v,Hid->pd,report,Hid->caps.InputReportByteLength);
SetValue3Decimals(Wnd,0x76,v);
HidP_GetScaledUsageValue(HidP_Input,0x84,0,0x36,&v,Hid->pd,report,Hid->caps.InputReportByteLength);
SetDlgItemInt(Wnd,0x77,v,TRUE);
}
// Zeigt Uhrzeit vom VorlaufempfΣnger
static void ShowHidRep2(HWND Wnd, const THid*Hid) {
PUCHAR report=LocalAlloc(LPTR,Hid->caps.FeatureReportByteLength);
if (report) {
TCHAR s[32];
SYSTEMTIME st;
HidP_InitializeReportForID(HidP_Feature,2,Hid->pd,report,Hid->caps.FeatureReportByteLength);
HidD_GetFeature(Hid->hDev,report,Hid->caps.FeatureReportByteLength); // Uhrzeit
st.wMilliseconds=report[1]*4; st.wSecond=report[2]; st.wMinute=report[3]; st.wHour=report[4];
st.wDay=report[5]; st.wDayOfWeek=report[6]; st.wMonth=report[7]; st.wYear=report[8]+2000;
if (SystemTimeToString(&st,DATE_SHORTDATE,0,s,elemof(s))) {
SetDlgItemText(Wnd,0x75,s);
// TODO: PC-Uhr stellen, aber nur 1x!
}else SetDlgItemText(Wnd,0x75,T("--"));
LocalFree(report);
}
}
// Zeigt unverΣnderliche Setup-Sachen
static void ShowHidRep3(HWND Wnd, const THid*Hid) {
PUCHAR report=LocalAlloc(LPTR,Hid->caps.FeatureReportByteLength);
if (report) {
long v;
HidP_InitializeReportForID(HidP_Feature,3,Hid->pd,report,Hid->caps.FeatureReportByteLength);
HidD_GetFeature(Hid->hDev,report,Hid->caps.FeatureReportByteLength); // Setup-Sachen
HidP_GetUsageValue(HidP_Feature,0xFF00,0,0x35,&v,Hid->pd,report,Hid->caps.FeatureReportByteLength);
SendDlgItemMessage(Wnd,0x72,CB_SETCURSEL,v,0); // Akkutyp
HidP_GetScaledUsageValue(HidP_Feature,0xFF00,0,0x36,&v,Hid->pd,report,Hid->caps.FeatureReportByteLength);
SetValue3Decimals(Wnd,0x73,v); // Ladeschluss
HidP_GetScaledUsageValue(HidP_Feature,0xFF00,0,0x37,&v,Hid->pd,report,Hid->caps.FeatureReportByteLength);
SetValue3Decimals(Wnd,0x74,v); // Entladeschluss
LocalFree(report);
}
}
// HID-Feature-Reports abfragen und einsetzen, wird bei Selektion aufgerufen.
static void FillHidInfos(HWND Wnd, const THid*Hid) {
PUCHAR report=LocalAlloc(LPTR,GetMaxReport(&Hid->caps));
if (report) {
OVERLAPPED o;
zeroOverlapped(&o);
o.hEvent=CreateEvent(NULL,FALSE,FALSE,NULL);
if (o.hEvent) {
HidP_InitializeReportForID(HidP_Input,4,Hid->pd,report,Hid->caps.InputReportByteLength);
GetInputReport(Hid->hDev,report,Hid->caps.InputReportByteLength,&o);
CloseHandle(o.hEvent);
FillHidRep4(Wnd,Hid,report);
}
LocalFree(report);
}
ShowHidRep2(Wnd,Hid);
ShowHidRep3(Wnd,Hid);
}
// Hilfsfunktion fⁿr die Eingabefehlerprⁿfung
static int cbGetCurSel(HWND Wnd, UINT id, HWND *w) {
return ComboBox_GetCurSel(*w=GetDlgItem(Wnd,id));
}
// Hilfsfunktion, bei Selektionswechsel
static INT_PTR cbGetCurItemData(HWND cb) {
return ComboBox_GetItemData(cb,ComboBox_GetCurSel(cb));
}
// Per Timer aufgeschobene DeviceChange-Reaktionsroutine
static void OnDeviceChange(HWND Wnd) {
HWND hCombo;
bool one;
UINT i,k;
HANDLE devs;
GUID hidGuid;
// serielle Schnittstellen listen (bei jedem WM_DEVICECHANGE bspw. fⁿr USB)
// Die SetupDi-Methode ist viel schneller als alle (256?) COM-Ports auszuprobieren,
// geht aber erst ab Win98 und Win2k. Win95 und NT4 bleiben au▀en vor.
// Es gibt GUID_DEVCLASS_PORTS -> listet serielle und parallele Schnittstellen, OHNE DIGCF_DEVICEINTERFACE
// und GUID_CLASS_COMPORT == GUID_DEVINTERFACE_COMPORT, nur serielle, MIT DIGCF_DEVICEINTERFACE
// ▄berraschung: Letzteres funktioniert nicht unter Win98SE! Was fⁿr ein heilloses Chaos.
// CM_Open_DevNode_Key() ist ersetzt durch SetupDiOpenDevRegKey().
// if (!bc || bc->dbcc_devicetype==DBT_DEVTYP_DEVICEINTERFACE && !CompareGuid(&bc->dbcc_classguid,&GUID_DEVINTERFACE_COMPORT)
hCombo=GetDlgItem(Wnd,0x21);
ComboBox_ResetContent(hCombo);
one=false;
devs=SetupDiGetClassDevs(&GUID_DEVCLASS_PORTS,NULL,0,DIGCF_PRESENT);
if (devs!=INVALID_HANDLE_VALUE) {
SP_DEVINFO_DATA devInfo;
devInfo.cbSize=sizeof devInfo;
for (i=0; SetupDiEnumDeviceInfo(devs,i,&devInfo); i++) {
HKEY hKey;
TCHAR s[16];
DWORD slen=sizeof s;
*s=0;
if ((hKey=SetupDiOpenDevRegKey(devs,&devInfo,DICS_FLAG_GLOBAL,0,DIREG_DEV,KEY_READ))
==INVALID_HANDLE_VALUE) continue;
RegQueryValueEx(hKey,T("PortName"),NULL,NULL,(LPBYTE)s,&slen);
RegCloseKey(hKey);
if (*s=='C') { // FehlschlΣge und LPTx ausfiltern
cbAddItem(hCombo,StrToInt(s+3)-1,Config.SerialNo,NULL,s); // nullbasiert
one=true;
}
}
SetupDiDestroyDeviceInfoList(devs);
}
// wine BUG: Workaround: SetupApi-Funktionen sind anscheinend komplett tot
#define MAXCOMSEARCH 2
if (!one) {
for (i=0; i<MAXCOMSEARCH; i++) { // nullbasiert
TCHAR ComName[8];
wnsprintf(ComName,elemof(ComName),T("COM%u"),i+1);
devs=CreateFile(ComName,0,0,0,OPEN_EXISTING,0,0);
if (devs!=INVALID_HANDLE_VALUE) {
CloseHandle(devs);
cbAddItem(hCombo,i,Config.SerialNo,NULL,ComName);
one=true;
}
}
}
EnableDlgItem(Wnd,0x10,one);
// Soundkarten (nur bei ─nderung der Anzahl auffrischen)
hCombo=GetDlgItem(Wnd,0x41);
k=waveInGetNumDevs();
if (ComboBox_GetCount(hCombo)!=k) {
ComboBox_ResetContent(hCombo);
one=false;
for (i=WAVE_MAPPER; (int)i<(int)k; i++) {
WAVEINCAPS wc;
if (!waveInGetDevCaps(i,&wc,sizeof wc)) {
if (cbAddItem(hCombo,i,Config.iSoundCard,NULL,wc.szPname)) {
FillSamplerates(Wnd); // Sampleraten auffⁿllen lassen
}
one=true;
}
}
EnableDlgItem(Wnd,0x12,one);
}
// Joysticks (nur bei ─nderung der Anzahl auffrischen)
hCombo=GetDlgItem(Wnd,0x51);
k=joyGetNumDevs();
if (ComboBox_GetCount(hCombo)!=k) {
ComboBox_ResetContent(hCombo);
one=false;
for (i=0; i<k; i++) {
JOYCAPS jc;
if (!joyGetDevCaps(i,&jc,sizeof jc)) {
if (cbAddItem(hCombo,i,Config.iJoystick,T("%d: %s"),i,jc.szPname)) {
FillButtons(Wnd);
}
one=true;
}
}
EnableDlgItem(Wnd,0x13,one);
}
// UsbPrn
hCombo=GetDlgItem(Wnd,0x61);
ComboBox_ResetContent(hCombo);
one=false;
devs=SetupDiGetClassDevs(&GUID_DEVINTERFACE_USBPRINT,0,0,DIGCF_PRESENT|DIGCF_DEVICEINTERFACE);
if (devs!=INVALID_HANDLE_VALUE) {
SP_DEVICE_INTERFACE_DATA devinterface;
devinterface.cbSize=sizeof devinterface;
for (i=0; SetupDiEnumDeviceInterfaces(devs,NULL,&GUID_DEVINTERFACE_USBPRINT,i,&devinterface); i++) {
cbAddItem(hCombo,i,Config.iUsbPrn,T("%d"),i);
one=true;
}
SetupDiDestroyDeviceInfoList(devs);
}
EnableDlgItem(Wnd,0x14,one);
// VorlaufempfΣnger
hCombo=GetDlgItem(Wnd,0x71);
ComboBox_ResetContent(hCombo);
one=false;
HidD_GetHidGuid(&hidGuid);
devs=SetupDiGetClassDevs(&hidGuid,0,0,DIGCF_PRESENT|DIGCF_DEVICEINTERFACE);
if (devs!=INVALID_HANDLE_VALUE) {
SP_DEVICE_INTERFACE_DATA devinterface;
devinterface.cbSize=sizeof devinterface;
for (i=0; SetupDiEnumDeviceInterfaces(devs,NULL,&hidGuid,i,&devinterface); i++) {
THid Hid;
union{
SP_DEVICE_INTERFACE_DETAIL_DATA detail;
TCHAR space[MAX_PATH+4];
WCHAR ps[128]; // ProductString
HIDD_ATTRIBUTES a;
}u;
SP_DEVINFO_DATA info;
info.cbSize=sizeof info;
u.detail.cbSize=sizeof u.detail;
if (!SetupDiGetDeviceInterfaceDetail(devs,&devinterface,&u.detail,sizeof u,NULL,&info)) continue;
Hid.hDev=CreateFile(u.detail.DevicePath,GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,NULL);
if (Hid.hDev!=INVALID_HANDLE_VALUE) {
HidD_GetAttributes(Hid.hDev,&u.a);
if (*(DWORD*)&u.a.VendorID==0x27D916C0 // VOTI->V-USB->HID mit Seriennummer muss es sein
&& HidD_GetProductString(Hid.hDev,u.ps,elemof(u.ps))) {
#ifdef UNICODE
PTSTR p=u.ps;
int l=lstrlen(p)+1;
#else
PTSTR p=u.space+128; // Hoffnung: Keine ▄berlappung (64 Zeichen vom GerΣt maximal)
int l=WideCharToMultiByte(CP_ACP,0,u.ps,-1,p,MAX_PATH-124,NULL,NULL);
#endif
if (StrStr(p,T("FunkUsb"))) { // Der Produktname muss "FunkUsb" enthalten
SetupDiSetDeviceRegistryProperty(devs,&info,SPDRP_FRIENDLYNAME,
(PBYTE)(p),l*sizeof(TCHAR)); // FriendlyName fⁿr GerΣte-Manager setzen
if (HidD_GetPreparsedData(Hid.hDev,&Hid.pd)) {
HidP_GetCaps(Hid.pd,&Hid.caps);
if (Hid.caps.UsagePage>=8) { // Joystick (Generic Desktop) hier ausfiltern
if (cbAddItem(hCombo,i,Config.iUsbHid,T("%d: %s"),i,p)) {
FillHidInfos(Wnd,&Hid);
}
one=true;
}
HidD_FreePreparsedData(Hid.pd);
}
}
}
CloseHandle(Hid.hDev);
}
}
SetupDiDestroyDeviceInfoList(devs);
}
EnableDlgItem(Wnd,0x15,one);
}
// Dialogfensterprozedur fⁿr Eigenschaftsseite
INT_PTR CALLBACK HardwareDlgProc(HWND Wnd,UINT Msg,WPARAM wParam,LPARAM lParam) {
DefHelpProc(Wnd,Msg,lParam,101);
switch (Msg) {
case WM_INITDIALOG: {
// Eingabeleitungen in der Bit-Reihenfolge von 3F6h, Pin-Nummern: 9pol. SubD
static const char SerialInLines[]=
"CTS(8)\0DSR(6)\0RI(9)\0DCD(1)\0RxD(2)\0";
// Ausgabeleitungen in der Bit-Reihenfolge von 3F4h
static const char SerialOutLines[]=
"DTR(4)\0RTS(7)\0TxD(3)\0";
CheckDlgButton(Wnd,0x10+Config.Where,TRUE);
AttachUpDown(Wnd,0x43,0x44,10,Config.iSampleRate*500,FiltFreqHz(NULL));
KillTimer(Wnd,0x43);
ShowWhere(Wnd);
cbFillA(GetDlgItem(Wnd,0x22),SerialInLines,Config.SerialLineIn);
cbFillA(GetDlgItem(Wnd,0x23),SerialOutLines,Config.SerialLineOut);
SendDlgItemMessage(Wnd,0x24,WM_SETFONT,(WPARAM)GdiObj.fnKursiv,FALSE);
cbFillAddrs(GetDlgItem(Wnd,0x31));
cbFillBits(GetDlgItem(Wnd,0x32),Config.ParallelLineIn);
cbFillBits(GetDlgItem(Wnd,0x33),Config.ParallelLineOut);
SendDlgItemMessage(Wnd,0x34,WM_SETFONT,(WPARAM)GdiObj.fnKursiv,FALSE);
PrepareRedString(GetDlgItem(Wnd,0x35));
SendDlgItemMessage(Wnd,0x45,WM_SETFONT,(WPARAM)GdiObj.fnKursiv,FALSE);
cbFillBits(GetDlgItem(Wnd,0x62),(BYTE)(Config.iUsbInput|0x80));
cbFillFromStringId(GetDlgItem(Wnd,0x72),22); // Akkutyp
OnDeviceChange(Wnd);
}return TRUE;
case WM_DEVICECHANGE: SetTimer(Wnd,0x10,1500,NULL); break;
case WM_COMMAND: switch ((DWORD)wParam) {
case MAKELONG(0x10,BN_CLICKED):
case MAKELONG(0x11,BN_CLICKED):
case MAKELONG(0x12,BN_CLICKED):
case MAKELONG(0x13,BN_CLICKED):
case MAKELONG(0x14,BN_CLICKED):
case MAKELONG(0x15,BN_CLICKED): {
BYTE o=Config.Where;
bool scc,piep;
// BS_AUTORADIOBUTTON funktioniert nicht mit ausgegrauten Kn÷pfen.
// Das Unglⁿck passiert, wenn man bei verschwundener Hardware (etwa HID)
// eine andere (etwa COM) anwΣhlt: Der Checkmark (bei HID) bleibt stehen.
// Deshalb dieser Umweg.
CheckRadioButton(Wnd,0x10,0x15,(int)wParam);
Config.Where=(BYTE)wParam-0x10;
scc=(o==2)!=(Config.Where==2); // Soundkarten-Wechsel?
piep=scc && Config.Piep
&& (AnimYes() || Empfang.DauerPiep); // Piep-Wechsel?
ShowWhere(Wnd);
// VorlaufempfΣnger-Uhr-Anzeige ein/ausschalten
if (o==5) KillTimer(Wnd,0x71);
if (Config.Where==5) SetTimer(Wnd,0x71,1000,NULL);
// Der Piep kann (auf manchen Soundkarten?) nicht gleichzeitg mit dem Empfang
// via Soundkarte laufen. Daher muss dieser entsprechend aktiviert/deaktiviert werden.
if (Config.Where==2 && piep) DoneBeep();
// Ggf. Demodulator-Eigenschaftsseite hinzufⁿgen oder entfernen.
if (scc && Config.Where==2) PropInsDelSheet(8,8);
RestartEmpfang();
if (scc && Config.Where!=2) PropInsDelSheet(-1,Decrypt?8:7);
if (o==2 && piep) {
InitBeep((BYTE)(10-Config.Piep));
if (Empfang.Signal || Empfang.DauerPiep) StartBeep();
}
}break;
case MAKELONG(0x21,CBN_SELCHANGE): {
BYTE b=(BYTE)cbGetCurItemData((HWND)lParam);
if (Config.SerialNo!=b) {
Config.SerialNo=b;
RestartEmpfang();
}
}break;
case MAKELONG(0x22,CBN_SELCHANGE): {
BYTE b=(BYTE)ComboBox_GetCurSel((HWND)lParam);
if (Config.SerialLineIn!=b) {
Config.SerialLineIn=b;
RestartEmpfang(); // wirklich n÷tig?
}
}break;
case MAKELONG(0x23,CBN_SELCHANGE): {
BYTE b=(BYTE)ComboBox_GetCurSel((HWND)lParam);
if (Config.SerialLineOut!=b) {
Config.SerialLineOut=b;
RestartEmpfang(); // wirklich n÷tig?
}
}break;
case MAKELONG(0x31,CBN_SELCHANGE): // OnParallelAddrChange(Wnd); break; // sofort
case MAKELONG(0x31,CBN_EDITCHANGE): { // verz÷gert
if (!SetTimer(Wnd,31,200,NULL)) PostMessage(Wnd,WM_TIMER,31,0);
}break;
case MAKELONG(0x32,CBN_SELCHANGE): {
BYTE b=(BYTE)cbGetCurItemData((HWND)lParam);
if (Config.ParallelLineIn!=b) {
Config.ParallelLineIn=b;
RestartEmpfang();
}
}break;
case MAKELONG(0x33,CBN_SELCHANGE): {
BYTE b=(BYTE)cbGetCurItemData((HWND)lParam);
if (Config.ParallelLineOut!=b) {
Config.ParallelLineOut=b;
RestartEmpfang();
}
}break;
case MAKELONG(0x41,CBN_SELCHANGE): {
int b=(int)cbGetCurItemData((HWND)lParam);
if (Config.iSoundCard!=(char)b) {
Config.iSoundCard=(char)b;
FillSamplerates(Wnd);
RestartEmpfang();
}
}break;
case MAKELONG(0x42,CBN_SELCHANGE):
case MAKELONG(0x42,CBN_EDITCHANGE): {
if (!SetTimer(Wnd,0x42,200,NULL)) PostMessage(Wnd,WM_TIMER,0x42,0);
}break;
case MAKELONG(0x43,EN_CHANGE): {
if (!SetTimer(Wnd,0x43,200,NULL)) PostMessage(Wnd,WM_TIMER,0x43,0);
}break;
case MAKELONG(0x51,CBN_SELCHANGE): {
int b=(int)cbGetCurItemData((HWND)lParam);
if (Config.iJoystick!=(BYTE)b) {
Config.iJoystick=(BYTE)b;
FillButtons(Wnd);
RestartEmpfang();
}
}break;
case MAKELONG(0x52,CBN_SELCHANGE): {
Config.iJoyButton=(BYTE)(Config.iJoyButton&0xE0|ComboBox_GetCurSel((HWND)lParam)); // wirkt sofort
}break;
case MAKELONG(0x53,CBN_SELCHANGE): {
Config.iJoyButton=(BYTE)(Config.iJoyButton&0x1F|ComboBox_GetCurSel((HWND)lParam)<<5);
}break;
case MAKELONG(0x61,CBN_SELCHANGE): {
BYTE b=(BYTE)ComboBox_GetCurSel((HWND)lParam);
if (Config.iUsbPrn!=b) {
Config.iUsbPrn=b;
RestartEmpfang();
}
}break;
case MAKELONG(0x62,CBN_SELCHANGE): {
Config.iUsbInput=(BYTE)(ComboBox_GetCurSel((HWND)lParam)+013); // oktal; wirkt sofort
}break;
case MAKELONG(0x71,CBN_SELCHANGE): {
BYTE b=(BYTE)cbGetCurItemData((HWND)lParam);
if (Config.iUsbHid!=b) {
Config.iUsbHid=b;
RestartEmpfang();
}
}break;
}break;
case WM_TIMER: if ((BYTE)wParam!=0x71) KillTimer(Wnd,wParam); switch ((BYTE)wParam) {
case 0x10: OnDeviceChange(Wnd); break;
case 0x31: OnParallelAddrChange(Wnd); break;
case 0x42: { // Abtastrate in Sa/s
int i=GetDlgItemInt(Wnd,0x42,NULL,FALSE)/1000;
if (i>=8 && i<256) {
Config.iSampleRate=(BYTE)i; // abspeichern in kSa/s
SendDlgItemMessage(Wnd,0x44,UDM_SETRANGE32,10,i*500);
RestartEmpfang();
}
}break;
case 0x43: {
int f;
if (GetUpDownInt(Wnd,0x44,&f)) SetFiltFreq(f*100); // Demodulatoroszillator äziehenô, AFC-Wert l÷schen
}break;
// case 0x71: ShowHidRep2(Wnd,Th.hCom,Th.pd,&Th.caps); break;
}break;
case WM_FUNKRECV: if ((BYTE)wParam==14) {
FillHidRep4(Wnd,&gHid,(PUCHAR)lParam);
}break;
case WM_CTLCOLORSTATIC: if (GetDlgCtrlID((HWND)lParam)==0x35) {
LRESULT br=DefWindowProc(Wnd,Msg,wParam,lParam);
SetTextColor((HDC)wParam,RGB(192,0,0)); // dunkelrot
SetBkMode((HDC)wParam,TRANSPARENT);
return (BOOL)br; // nicht "return (BOOL)GetSysColorBrush(COLOR_3DFACE);" // Unter Win7 falsche Hintergrundfarbe
}break;
case WM_NOTIFY: {
LPPSHNOTIFY psn=(LPPSHNOTIFY)lParam;
UINT i,Problem=0; // Problem = String-ID, die bei festgestelltem Problem angezeigt wird
HWND w; // Fehler-Dialogelement, wird anschlie▀end fokussiert und ggf. Text markiert
switch (psn->hdr.code) {
case PSN_SETACTIVE: {
SendDlgItemMessage(Wnd,0x44,UDM_SETPOS32,0,Config.iFiltFreq<<1);
if (Config.Where==5) SetTimer(Wnd,0x71,1000,NULL);
}break;
case PSN_KILLACTIVE: {
switch (Config.Where) {
case 0: { // seriell
if (cbGetCurSel(Wnd,0x21,&w)<0) {Problem=17; break;}
if (cbGetCurSel(Wnd,0x22,&w)<0) {Problem=17; break;}
if (cbGetCurSel(Wnd,0x23,&w)<0) {Problem=17; break;}
}break;
case 1: { // parallel
if (!OnParallelAddrChange(Wnd)) {
Problem=18;
w=GetDlgItem(Wnd,0x31);
break;
}
if (cbGetCurSel(Wnd,0x32,&w)<0) {Problem=17; break;}
if (cbGetCurSel(Wnd,0x33,&w)<0) {Problem=17; break;}
}break;
case 2: { // Soundkarte
if (cbGetCurSel(Wnd,0x41,&w)<0) {Problem=17; break;}
i=GetDlgItemInt(Wnd,0x42,NULL,FALSE)/1000u; // Abtastrate
if (i<8 || i>255) {w=GetDlgItem(Wnd,0x42); Problem=46; break;}
if (!GetUpDownInt(Wnd,0x44,NULL)) { // Filterfrequenz
Edit_SetSel(w=GetDlgItem(Wnd,0x43),0,-1);
Problem=46;
break;
}
}break;
case 3: { // Joystick
if (cbGetCurSel(Wnd,0x51,&w)<0) {Problem=17; break;}
if (cbGetCurSel(Wnd,0x52,&w)<0) {Problem=17; break;}
}break;
case 4: { // UsbPrn
if (cbGetCurSel(Wnd,0x61,&w)<0) {Problem=17; break;}
if (cbGetCurSel(Wnd,0x62,&w)<0) {Problem=17; break;}
}break;
case 5: { // VorlaufempfΣnger
KillTimer(Wnd,0x71);
}break;
default: Problem=16; w=GetDlgItem(Wnd,0x10);
}
}break;
}
if (Problem) {
SetFocus(w);
MBox(Wnd,Problem,MB_OK);
return SetDlgMsgResult(Wnd,WM_NOTIFY,TRUE);
}
}break;
}
return FALSE;
}
Vorgefundene Kodierung: OEM (CP437) | 1
|
|