/* --------------------------------------------------------------
* Ressourcennamen für das Adress‑Tool (ANSI)
* -------------------------------------------------------------- */
#ifndef _RESOURCE_H_
#define _RESOURCE_H_
/* Dialogfenster */
#define IDD_MAIN_DIALOG 101
/* Edit‑Controls */
#define IDC_EDIT_NAME 1000
#define IDC_EDIT_STREET 1001
#define IDC_EDIT_PLZ 1002
#define IDC_EDIT_CITY 1003
/* Buttons */
#define IDC_BTN_NEW 2000
#define IDC_BTN_CHANGE 2001
#define IDC_BTN_DELETE 2002
#define IDC_BTN_SAVE 2003
#define IDC_BTN_FIND 2004
#define IDC_BTN_EXIT 2005
#endif /* _RESOURCE_H_ */
/* --------------------------------------------------------------
* resource.rc – Dialog-Template
* -------------------------------------------------------------- */
#include "resource.h"
IDD_MAIN_DIALOG DIALOGEX 0,0,260,180
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Adressdatenbank"
FONT 9, "Segoe UI"
BEGIN
/* Labels: Rechtsbündig (professioneller UI-Design) */
RTEXT "Name:", -1, 20, 15, 40, 10
RTEXT "Straße:", -1, 20, 35, 40, 10
RTEXT "PLZ:", -1, 20, 55, 40, 10
RTEXT "Ort:", -1, 20, 75, 40, 10
/* Edit-Fields */
EDITTEXT IDC_EDIT_NAME, 60, 15, 180, 12, ES_AUTOHSCROLL
EDITTEXT IDC_EDIT_STREET, 60, 35, 180, 12, ES_AUTOHSCROLL
EDITTEXT IDC_EDIT_PLZ, 60, 55, 80, 12, ES_NUMBER | ES_AUTOHSCROLL
EDITTEXT IDC_EDIT_CITY, 60, 75, 180, 12, ES_AUTOHSCROLL
/* Buttons */
PUSHBUTTON "Neu", IDC_BTN_NEW, 10,110,45,14
PUSHBUTTON "Ändern", IDC_BTN_CHANGE, 65,110,45,14
PUSHBUTTON "Löschen", IDC_BTN_DELETE, 120,110,45,14
PUSHBUTTON "Speichern",IDC_BTN_SAVE, 175,110,45,14
PUSHBUTTON "Suchen", IDC_BTN_FIND, 10,135,45,14
PUSHBUTTON "Ende", IDC_BTN_EXIT, 120,135,45,14
END
/* -------------------------------------------------------------- * main.c – Win32 C Anwendung (ANSI) * -------------------------------------------------------------- */ #include#include #include #include "resource.h" /* Globale Handles */ static HWND hDlg; static HINSTANCE hInst; #define DATA_FILE _T("data.txt") typedef LRESULT (CALLBACK *PFN_WNDPROC)(HWND, UINT, WPARAM, LPARAM); static PFN_WNDPROC OldEditProc[4] = {0}; static HWND hEditControls[4] = {0}; static COLORREF clrFocus = RGB(255, 255, 200); static COLORREF clrNormal = COLOR_WINDOW; /* Hilfsfunktionen */ static int FindRecord(const TCHAR* name, TCHAR* line, size_t lineSize); static void RewriteFile(const TCHAR* nameToSkip, const TCHAR* newEntry); static void ClearFields(void); static void LoadRecord(const TCHAR* name); static void SaveRecord(void); static void DeleteRecord(void); /* Dialog-Prozedur */ static INT_PTR CALLBACK DlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); /* WinMain */ int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrev, LPTSTR lpCmd, int nShow) { hInst = hInstance; DialogBox(hInstance, MAKEINTRESOURCE(IDD_MAIN_DIALOG), NULL, DlgProc); return 0; } static int FindRecord(const TCHAR* name, TCHAR* line, size_t lineSize) { FILE* fp = _tfopen(DATA_FILE, _T("r")); if (!fp) return -1; TCHAR buffer[512]; while (_fgetts(buffer, _countof(buffer), fp)) { TCHAR tmpLine[512]; _tcscpy_s(tmpLine, _countof(tmpLine), buffer); TCHAR* token = _tcsstr(tmpLine, TEXT("|")); if (!token) continue; *token = _T('\0'); if (_tcsicmp(tmpLine, name) == 0) { _tcscpy_s(line, lineSize, buffer); fclose(fp); return 0; } } fclose(fp); return -1; } static void RewriteFile(const TCHAR* nameToSkip, const TCHAR* newEntry) { if (nameToSkip == NULL) return; FILE* fpIn = _tfopen(DATA_FILE, _T("r")); FILE* fpOut = _tfopen(_T("tmp.txt"), _T("w")); if (!fpOut) { if (fpIn) fclose(fpIn); return; } if (fpIn) { TCHAR buffer[512]; while (_fgetts(buffer, _countof(buffer), fpIn)) { TCHAR tmpLine[512]; _tcscpy_s(tmpLine, _countof(tmpLine), buffer); TCHAR* token = _tcsstr(tmpLine, TEXT("|")); if (token) { *token = _T('\0'); if (_tcsicmp(tmpLine, nameToSkip) == 0) { fclose(fpIn); fclose(fpOut); goto replace_file; } } fputs(buffer, fpOut); } fclose(fpIn); } replace_file: if (newEntry) { FILE* fpAppend = _tfopen(_T("tmp.txt"), _T("a")); if (fpAppend) { _fputs(newEntry, fpAppend); fclose(fpAppend); } } _tremove(DATA_FILE); _trename(_T("tmp.txt"), DATA_FILE); } static void ClearFields(void) { for (int i = 0; i < 4; ++i) SetWindowText(hEditControls[i], _T("")); SetFocus(hEditControls[0]); } static void LoadRecord(const TCHAR* name) { TCHAR line[512]; if (FindRecord(name, line, _countof(line)) == 0) { TCHAR workLine[512]; _tcscpy_s(workLine, _countof(workLine), line); TCHAR* fields[4]; int fieldCount = 0; TCHAR* curr = workLine; while (fieldCount < 4) { fields[fieldCount++] = curr; TCHAR* next = _tcsstr(curr, TEXT("|")); if (!next) break; *next = _T('\0'); curr = next + 1; } for (int i = 0; i < fieldCount; ++i) SetWindowText(hEditControls[i], fields[i]); } else { MessageBox(hDlg, TEXT("Datensatz nicht gefunden!"), TEXT("Info"), MB_OK | MB_ICONINFORMATION); ClearFields(); } } static void SaveRecord(void) { TCHAR name[128], street[128], plz[64], city[128]; GetWindowText(hEditControls[0], name, _countof(name)); GetWindowText(hEditControls[1], street, _countof(street)); GetWindowText(hEditControls[2], plz, _countof(plz)); GetWindowText(hEditControls[3], city, _countof(city)); if (_tcslen(name) == 0) { MessageBox(hDlg, TEXT("Name darf nicht leer sein!"), TEXT("Info"), MB_OK | MB_ICONWARNING); return; } TCHAR entry[1024]; _stprintf_s(entry, _countof(entry), TEXT("%s|%s|%s|%s\r\n"), name, street, plz, city); RewriteFile(name, entry); MessageBox(hDlg, TEXT("Datensatz gespeichert."), TEXT("Info"), MB_OK | MB_ICONINFORMATION); } static void DeleteRecord(void) { TCHAR name[128]; GetWindowText(hEditControls[0], name, _countof(name)); if (_tcslen(name) == 0) { MessageBox(hDlg, TEXT("Bitte Namen eingeben."), TEXT("Info"), MB_OK | MB_ICONWARNING); return; } TCHAR confirmMsg[512]; _stprintf_s(confirmMsg, _countof(confirmMsg), TEXT("Soll der Datensatz '%s' wirklich gelöscht werden?"), name); if (MessageBox(hDlg, confirmMsg, TEXT("Löschen"), MB_YESNO | MB_ICONQUESTION) == IDYES) { RewriteFile(name, NULL); MessageBox(hDlg, TEXT("Gelöscht."), TEXT("Info"), MB_OK | MB_ICONINFORMATION); ClearFields(); } } static INT_PTR CALLBACK DlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_INITDIALOG: hDlg = hWnd; hEditControls[0] = GetDlgItem(hDlg, IDC_EDIT_NAME); hEditControls[1] = GetDlgItem(hDlg, IDC_EDIT_STREET); hEditControls[2] = GetDlgItem(hDlg, IDC_EDIT_PLZ); hEditControls[3] = GetDlgItem(hDlg, IDC_EDIT_CITY); for (int i = 0; i < 4; ++i) { OldEditProc[i] = (PFN_WNDPROC)SetWindowLongPtr( hEditControls[i], GWLP_WNDPROC, (LONG_PTR)EditSubclassProc); FOCUSSTATE* pState = (FOCUSSTATE*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(FOCUSSTATE)); SetWindowLongPtr(hEditControls[i], GWLP_USERDATA, (LONG_PTR)pState); } SetFocus(hEditControls[0]); return TRUE; case WM_CTLCOLOREDIT: { HDC hdc = (HDC)wParam; HWND hEdit = (HWND)lParam; FOCUSSTATE* pState = (FOCUSSTATE*)GetWindowLongPtr(hEdit, GWLP_USERDATA); COLORREF color = pState && pState->bFocused ? clrFocus : clrNormal; SetBkColor(hdc, color); if (pState && pState->bFocused) return (LRESULT)CreateSolidBrush(color); else return (LRESULT)GetStockObject(WHITE_BRUSH); } case WM_COMMAND: if (HIWORD(wParam) == BN_CLICKED) { int id = LOWORD(wParam); switch (id) { case IDC_BTN_NEW: ClearFields(); break; case IDC_BTN_SAVE: SaveRecord(); break; case IDC_BTN_DELETE: DeleteRecord(); break; case IDC_BTN_FIND: { TCHAR name[128]; GetWindowText(hEditControls[0], name, _countof(name)); if (_tcslen(name) > 0) LoadRecord(name); else MessageBox(hDlg, TEXT("Name fehlt!"), TEXT("Info"), MB_OK | MB_ICONWARNING); } break; case IDC_BTN_EXIT: EndDialog(hDlg, IDOK); return TRUE; } } return TRUE; case WM_CLOSE: for (int i = 0; i < 4; ++i) SetWindowLongPtr(hEditControls[i], GWLP_WNDPROC, (LONG_PTR)OldEditProc[i]); EndDialog(hDlg, IDCANCEL); return TRUE; case WM_DESTROY: for (int i = 0; i < 4; ++i) { FOCUSSTATE* pState = (FOCUSSTATE*)GetWindowLongPtr( hEditControls[i], GWLP_USERDATA); if (pState) HeapFree(GetProcessHeap(), 0, pState); } break; } return FALSE; } /* Fenster-Prozedur für Edit-Controls */ LRESULT CALLBACK EditSubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_SETFOCUS: FOCUSSTATE* pState = (FOCUSSTATE*)GetWindowLongPtr(hWnd, GWLP_USERDATA); if (!pState) return DefWindowProc(hWnd, uMsg, wParam, lParam); pState->bFocused = TRUE; InvalidateRect(hWnd, NULL, TRUE); break; case WM_KILLFOCUS: FOCUSSTATE* pState = (FOCUSSTATE*)GetWindowLongPtr(hWnd, GWLP_USERDATA); if (!pState) return DefWindowProc(hWnd, uMsg, wParam, lParam); pState->bFocused = FALSE; InvalidateRect(hWnd, NULL, TRUE); break; case WM_KEYDOWN: if (wParam == VK_RETURN) { int id = GetDlgCtrlID(hWnd); switch (id) { case IDC_EDIT_NAME: SetFocus(hEditControls[1]); break; case IDC_EDIT_STREET: SetFocus(hEditControls[2]); break; case IDC_EDIT_PLZ: SetFocus(hEditControls[3]); break; case IDC_EDIT_CITY: SendMessage(hDlg, WM_COMMAND, IDC_BTN_SAVE, BN_CLICKED); return 0; } } break; default: return CallWindowProc((PFN_WNDPROC)GetWindowLongPtr(hWnd, GWLP_USERDATA), hWnd, uMsg, wParam, lParam); } return DefWindowProc(hWnd, uMsg, wParam, lParam); }
main.c, resource.h und resource.rc müssen hinzugefügt werden.data.txt im gleichen Verzeichnis wie die EXE gespeichert.RewriteFile verhindert Abstürze._stprintf_s verhindern Buffer-Overflows.WM_CTLCOLOREDIT zurückgegeben.Das Tool ist vollständig funktionsfähig, sicher und kann als Beispiel für einfache Win32-C-Anwendungen verwendet werden.