#include #include #include #define ID_LISTBOX 100 #define MY_TIMER 102 #define TIMER_PERIOD 750 HWND hListbox, hwnd; bool bFirstInstance = true; HANDLE myEvent; LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM); char szClassName[] = "CodeBlocksWindowsApp"; char szTitle[] = "Code::Blocks Template Windows App"; BOOL InitWndClass(HINSTANCE hThisInstance) { WNDCLASSEX wincl; wincl.hInstance = hThisInstance; wincl.lpszClassName = szClassName; wincl.lpfnWndProc = WindowProcedure; wincl.style = CS_DBLCLKS; wincl.cbSize = sizeof (WNDCLASSEX); wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION); wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION); wincl.hCursor = LoadCursor (NULL, IDC_ARROW); wincl.lpszMenuName = NULL; wincl.cbClsExtra = 0; wincl.cbWndExtra = 0; wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND; // Неудача при регистрации класса окна if (!RegisterClassEx (&wincl)) { return FALSE; } return TRUE; } bool IsFirstInstance() { HANDLE hMutex = OpenMutex(MUTEX_ALL_ACCESS, 0, "VolvoMutex1.0"); if (!hMutex) { // если программа запускается первый раз, то создаем Mutex hMutex = CreateMutex(0, 0, "VolvoMutex1.0"); return true; } return false; } int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nCmdShow) { MSG messages; bFirstInstance = IsFirstInstance(); // Регистрируем класс окна в любом случае if(!InitWndClass(hThisInstance)) { return 0; } // Создаем класс окна hwnd = CreateWindowEx(0, szClassName, (bFirstInstance ? szTitle : ""), // первая копия - szTitle, остальные - пусто WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 544, 375, HWND_DESKTOP, NULL, hThisInstance, NULL); if(bFirstInstance) { // Первая копия приложения: hListbox = CreateWindow("LISTBOX", NULL, (WS_CHILD | LBS_STANDARD | WS_VSCROLL | LBS_DISABLENOSCROLL | WS_VISIBLE) & (~LBS_SORT), 30, 30, 400, 320, hwnd, (HMENU)ID_LISTBOX, hThisInstance, NULL ); ShowWindow (hwnd, nCmdShow); // Информация... SendMessage(hListbox, LB_ADDSTRING, 0, (LPARAM)"First instance of application"); // Создаем событие ... myEvent = CreateEvent(NULL, FALSE, FALSE, "VolvoTestEvent"); // ... и устанавливаем его SetEvent(myEvent); } else { // Не первый экземпляр: // Находим первую копию - единственную, у которой есть окно с заголовком ... HWND first_inst = FindWindow(NULL, szTitle); if(first_inst) { // ... и переносим его на первый план, если нашли SetForegroundWindow(first_inst); // Находим в окне первой копии ListBox, куда будем записывать hListbox = FindWindowEx(first_inst, NULL, "listbox", NULL); if(hListbox) { // Информация SendMessage(hListbox, LB_ADDSTRING, 0, (LPARAM)"Another instance of application"); } else { // Не нашли ListBox MessageBox(NULL, "Cannot find LISTBOX control", "Error", MB_OK | MB_ICONEXCLAMATION); } } else { // Не нашли окно первой копии MessageBox(NULL, "Cannot find first-instance window", "Error", MB_OK | MB_ICONEXCLAMATION); } // Получаем созданный ранее Event myEvent = OpenEvent(EVENT_ALL_ACCESS, FALSE, "VolvoTestEvent"); } // Все, разные действия для первой и не первой копии закончились... // Теперь для любой копии устанавливаем таймер SetTimer(hwnd, MY_TIMER, TIMER_PERIOD, NULL); // И запускаем основной цикл обрабртки сообщений while (GetMessage (&messages, NULL, 0, 0)) { TranslateMessage(&messages); DispatchMessage(&messages); } return messages.wParam; } // Callback-функция, будет использоваться при закрытии первой копии приложения BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam) { HWND hWndFirst = (HWND)lParam; if(hwnd != hWndFirst) { char s[256] = ""; GetClassName(hwnd, s, 256); if(!strcmp(s, szClassName)) { PostMessage(hwnd, WM_DESTROY, 0, 0); } } return TRUE; } LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_TIMER: { // Ждем наступления события WaitForSingleObject(myEvent, INFINITE); char s[50] = {0}; sprintf(s, "Event: %d", myEvent); // Информация - откуда приходят данные SendMessage(hListbox, LB_ADDSTRING, 0, (LPARAM)s); for(int i = 0; i < 5; i++) { // считаем и показываем, что что-то происходит sprintf(s, "App = %d; n = %d", hwnd, i); SendMessage(hListbox, LB_ADDSTRING, 0, (LPARAM)s); } SendMessage(hListbox, LB_SETCARETINDEX, SendMessage(hListbox, LB_GETCOUNT, 0, 0), TRUE); SetEvent(myEvent); break; } case WM_DESTROY: if(bFirstInstance) { EnumWindows(&EnumWindowsProc, (LPARAM)hwnd); } CloseHandle(myEvent); KillTimer(hwnd, MY_TIMER); PostQuitMessage(0); break; default: return DefWindowProc (hwnd, message, wParam, lParam); } return 0; }