1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
| #include "stdafx.h"
#include "lab6.h"
#include "windows.h"
#include <CommCtrl.h>
HINSTANCE hInst;
bool bSecondInstance;
HWND hWnd;
int APIENTRY WinMain(HINSTANCE hInstance, /* дескриптор текущего экземпляра приложения Дескриптор hInstance чаще всего требуется функциям, работающим с ресурсами программы.*/
HINSTANCE hPrevInstance, /** дескриптор предыдущего экземпляра приложения , по умолчанию null */
LPTSTR lpCmdLine, /* указатель на начало командной строки, введенной при запуске программы. */
int nCmdShow) /* как окно должно быть показано */
{
MSG msg;//структура сообщения
bSecondInstance = FindWindow(NULL, CAPTION_1/*"chat1"*/) != NULL;
if (bSecondInstance && FindWindow(NULL, CAPTION_2/*"chat2"*/) != NULL)
{
MessageBox(NULL, // дескриптор родительского окна
"Два экземпляра программы уже запущены", // указатель на строку с сообщением
"Ошибка", // указатель на строку с текстом заголовка
MB_ICONEXCLAMATION);// флаги для отображения кнопок, стиля пиктограммы и прочее
return 1; // код завершения программы
}
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
MyRegisterClass(hInstance);
if (!InitInstance(hInstance, nCmdShow))
{
return FALSE;
}
//создание статуса - контекстное меню
HWND hStatusWindow = CreateStatusWindow(WS_CHILD | WS_VISIBLE, "", hWnd, 5000);
HMENU hMainMenu = CreateMenu();
HMENU hPopMenuFile = CreatePopupMenu();
HMENU hPopMenuStatus = CreatePopupMenu();
AppendMenu(hMainMenu, MF_STRING | MF_POPUP, (UINT)hPopMenuFile, "Файл");
{
AppendMenu(hPopMenuFile, MF_STRING, IDB_SEND, "Отправить данные");
AppendMenu(hPopMenuFile, MF_STRING, IDM_EXIT, "Выход");
}
AppendMenu(hMainMenu, MF_STRING | MF_POPUP, (UINT)hPopMenuStatus, "Статус");
{
AppendMenu(hPopMenuStatus, MF_STRING | MF_CHECKED | MF_UNCHECKED, IDB_ONLINE, "Онлайн");
AppendMenu(hPopMenuStatus, MF_STRING | MF_CHECKED | MF_UNCHECKED, IDB_BUSY, "Занят");
AppendMenu(hPopMenuStatus, MF_STRING | MF_CHECKED | MF_UNCHECKED, IDB_OUTOFPLACE, "Отошел");
AppendMenu(hPopMenuStatus, MF_STRING | MF_CHECKED | MF_UNCHECKED, IDB_DONOTBOTHER, "Не беспокоить");
}
SetMenu(hWnd, hMainMenu);
SetMenu(hWnd, hPopMenuFile);
SetMenu(hWnd, hPopMenuStatus);
//цикл сообщений приложения
while (GetMessage(&msg, // указатель на структуру MSG
NULL, // дескриптор окошка
0,// фильтры
0))// фильтры для выборки сообщений
{
if (!TranslateAccelerator(msg.hwnd, NULL, &msg))
{
TranslateMessage(&msg); ///Эта функция переводит сообщения формата виртуальных клавиш в сообщения символы.
DispatchMessage(&msg); ///Функция DispatchMessage должна вызвать «функцию обработки сообщений».
}
}
return (int)msg.wParam; // код завершения программы
}
HWND GetOtherClientHandle()
{
return FindWindow(NULL, bSecondInstance ? CAPTION_1 : CAPTION_2);
}
// Для создания класса его необходимо зарегистрировать.
// FUNCTION: MyRegisterClass()
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW; //стиль окна
wcex.lpfnWndProc = WndProc;//адрес функции обработки сообщений.
wcex.cbClsExtra = 0; // число освобождаемых байтов в конце структуры
wcex.cbWndExtra = 0; // число освобождаемых байтов при создании экземпляра приложения
wcex.hInstance = hInstance;//дискриптор экземпляра приложения
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_LAB6));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);//загрузка курсора
wcex.hbrBackground = (HBRUSH)GetStockObject(COLOR_3DFACE); // дескриптор кисти для закраски фона окна
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_LAB6);
wcex.lpszClassName = CLASS_NAME; //название класса
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
return RegisterClassEx(&wcex);//регистрация класса
}
//создание главного окна
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance;
hWnd = CreateWindow// не расширенное окно(без EX)
(CLASS_NAME,//имя класса для создаваемого окна (это имя использовалось при регистрации класса).
bSecondInstance ? CAPTION_2 : CAPTION_1,//имя окна.
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,//стиль окна.
CW_USEDEFAULT, 0, //позиция x,y
300, 500,//ширина и высота
NULL,// используется для создания «дочернего окна»
NULL,//описатель меню
hInstance, //экземпляр приложения.
NULL);// указатель на пользовательский параметр окна.
// если окно не создано
if (!hWnd)
return FALSE;
ShowWindow(hWnd, nCmdShow);//функция показа окна
UpdateWindow(hWnd);// если что-то добавили то обновляем
return TRUE;
}
void ReceiveMessage(HWND hEdit, const char *msg)
{
size_t src_text_len = GetWindowTextLength(hEdit);
size_t full_len = src_text_len + strlen(msg) + 5;
char *fulltext = (char*)malloc(full_len);
if (src_text_len > 0)
{
GetWindowText(hEdit, fulltext, full_len);
strcat_s(fulltext, full_len, "\r\n");
}
else
{
fulltext[0] = 0;
}
strcat_s(fulltext, full_len, ">>");
strcat_s(fulltext, full_len, msg);
SetWindowText(hEdit, fulltext);
free(fulltext);
}
void SendTextMessage(HWND hMyWnd, HWND hEdit)
{
HWND hOtherWnd = FindWindow(NULL, bSecondInstance ? CAPTION_1 : CAPTION_2);
COPYDATASTRUCT cds;
if (!hOtherWnd)
{
MessageBox(hMyWnd, "Нету второго окна!", "Ошибка", MB_ICONEXCLAMATION);
return;
}
int textlen = GetWindowTextLength(hEdit) + 1;
if (textlen == 1)
{
MessageBox(hMyWnd, "Пустое сообщение!", "Ошибка", MB_ICONEXCLAMATION);
return;
}
char *message = (char*)malloc(textlen);
GetWindowText(hEdit, message, textlen);
// 1 параметр -Идентификатоp окна
// 2 параметр - буфеp, пpинимающий стpоку.
// 3 параметр -Размеp буфеpа
cds.lpData = message;
cds.cbData = textlen;
cds.dwData = COPYDATA_MSG;
SendMessage(hOtherWnd, WM_COPYDATA, (WPARAM)hMyWnd, (LPARAM)&cds);
free(message);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HWND hMsgEdit, hResponseEdit, hStatusEdit;
PCOPYDATASTRUCT pCDS1, pCDS2;
HWND hOtherWnd = FindWindow(NULL, bSecondInstance ? CAPTION_1 : CAPTION_2);
switch (message)
{
case WM_CREATE:
hResponseEdit = CREATE_EDIT(5, 10, 270, 100, ES_MULTILINE | WS_VSCROLL | ES_READONLY);
hMsgEdit = CREATE_EDIT(5, 150, 270, 100, ES_MULTILINE);
hStatusEdit = CREATE_EDIT(5, 300, 270, 50, ES_READONLY | IDB_ONLINE | IDB_DONOTBOTHER | IDB_BUSY | IDB_OUTOFPLACE);
CREATE_BUTTON(58, 380, 160, 30, "Отправить", IDB_SEND);
if (!hOtherWnd)
{
SetWindowText(hStatusEdit, TEXT(bSecondInstance ? CAPTION_1 : CAPTION_2 "\r\nНету в сети"));
}
else
{
SetWindowText(hStatusEdit, TEXT(bSecondInstance ? CAPTION_1 : CAPTION_2 "\r\nОнлайн"));
}
if (GetOtherClientHandle())
{
SendMessage(GetOtherClientHandle(), NULL, NULL, NULL);
}
break;
case WM_COPYDATA:
pCDS1 = (PCOPYDATASTRUCT)lParam;
pCDS2 = (PCOPYDATASTRUCT)lParam;
if (pCDS1->dwData == COPYDATA_MSG)
{
ReceiveMessage(hResponseEdit, (LPCSTR)pCDS1->lpData);
}
else if (pCDS2->dwData == COPYDATA_MSG)
{
ReceiveMessage(hStatusEdit, (LPCSTR)pCDS2->lpData);
}
case WM_COMMAND:
if (LOWORD(wParam) == IDB_ONLINE)
{
SetWindowText(hStatusEdit, TEXT(" Онлайн"));
SendTextMessage(hWnd, hStatusEdit);
}
else if (LOWORD(wParam) == IDB_BUSY)
{
SetWindowText(hStatusEdit, TEXT(" Занят"));
}
else if (LOWORD(wParam) == IDB_OUTOFPLACE)
{
SetWindowText(hStatusEdit, TEXT(" Отошел"));
}
else if (LOWORD(wParam) == IDB_DONOTBOTHER)
{
SetWindowText(hStatusEdit, TEXT(" Не беспокоить"));
}
switch (LOWORD(wParam))
{
case IDB_SEND:
case IDM_SENDMSG:
SendTextMessage(hWnd, hMsgEdit);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
} |