Операционная система Microsoft Windows 3.1 для программиста. Дополнительные главы

Файл ddeml/ddemlcl.cpp


// ---------------------------------------- // Приложение DDEMLCL // Клиент DDEML // ---------------------------------------- #define STRICT #include <windows.h>
#include <windowsx.h>
#include <ddeml.h>
#include <dde.h>
#include <mem.h>
#pragma hdrstop

#include "ddemlcl.hpp"

// Прототипы функций HCONV DDEClientOpen(HINSTANCE hInst, LPSTR szService, LPSTR szTopic, LPSTR szItem);
void DDEClientClose(HCONV);
BOOL DDESend(HCONV, LPSTR);
BOOL DDEReceive(HCONV, LPSTR szBuf, int nBufSize);
BOOL InitApp(HINSTANCE);
LRESULT CALLBACK _export WndProc(HWND, UINT, WPARAM, LPARAM);

// Имя класса окна char const szClassName[] = "DDEMLCLIENT";

// Заголовок окна char const szWindowTitle[] = "DDEML Client";

HWND hwnd; HINSTANCE hInst; HCONV hConv = NULL;

// ===================================== // Функция WinMain // ===================================== #pragma argsused

int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) { MSG msg;

// Можно запускать только одну копию приложения if(hPrevInstance) return FALSE;

// Инициализируем приложение if(!InitApp(hInstance)) return FALSE;

// Сохраняем идентификатор приложения hInst = hInstance;

hwnd = CreateWindow( szClassName, // имя класса окна szWindowTitle, // заголовок окна WS_OVERLAPPEDWINDOW, 20, 20, 250, 100, 0, 0, hInstance, NULL);

if(!hwnd) return FALSE;



ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);

while(GetMessage(&msg, 0, 0, 0)) { TranslateMessage(&msg);
DispatchMessage(&msg);
} return msg.wParam; }

// ===================================== // Функция InitApp // Выполняет регистрацию класса окна // =====================================

BOOL InitApp(HINSTANCE hInstance) { ATOM aWndClass; WNDCLASS wc;

memset(&wc, 0, sizeof(wc));
wc.lpszMenuName = "APP_MENU"; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = (WNDPROC) WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon(hInstance, "APP_ICON");
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH);
wc.lpszClassName = (LPSTR)szClassName; aWndClass = RegisterClass(&wc);
return (aWndClass != 0);
}




// ===================================== // Функция WndProc // =====================================

LRESULT CALLBACK _export WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRUCT ps;

switch (msg) { case WM_CREATE: { // Инициализируем DDEML и создаем канал связи if(hConv == NULL) { hConv = DDEClientOpen(hInst, (LPSTR)"BMPServer", (LPSTR)"BMPFile", (LPSTR)"DDEData");

// Если сервер не запущен, предоставляем // пользователю возможность запустить его if(hConv == NULL) { if(IDYES == MessageBox(hwnd, "Сервер не запущен.\nЗапустить?", "DDEML Client", MB_YESNO | MB_ICONHAND)) { WORD rc; // Выполняем попытку запуска сервера rc = WinExec("DDEMLSR", SW_SHOW);
if(rc < 32) { MessageBox(hwnd, "Невозможно запустить сервер", "DDEML Client", MB_ICONHAND);
return -1; } else { // После удачного запуска повторяем // попытку инициализации DDEML // и создания канала связи hConv = DDEClientOpen(hInst, (LPSTR)"BMPServer", (LPSTR)"BMPFile", (LPSTR)"DDEData");
if(hConv == NULL) return -1; else return 0; } } return -1; } return 0; } return 0; }

// Обработка сообщений от меню case WM_COMMAND: { switch (wParam) { case CM_HELPABOUT: { MessageBox(hwnd, "DDEML Client\nVersion 1.0\n" "(C) Frolov A.V., 1995", "About DDEML Client", MB_OK | MB_ICONINFORMATION);
return 0; }

// Завершаем работу приложения case CM_FILEEXIT: { DestroyWindow(hwnd);
return 0; }

// Посылаем текстовую строку серверу case CM_MSG_TO_SERVER: { if(!DDESend(hConv, (LPSTR)"c:\\nicebmp\\sky.bmp")) MessageBox(hwnd, "Сервер не отвечает", "DDEML Client", MB_OK);
return 0; }

// Принимаем текстовую строку от сервера case CM_MSG_FROM_SERVER: { BYTE szBuf[256]; if(DDEReceive(hConv, szBuf, 80L)) MessageBox(hwnd, szBuf, "DDEML Client", MB_OK);
else MessageBox(hwnd, "Сервер не отвечает", "DDEML Client", MB_OK);
return 0; } default: return 0; } }



case WM_DESTROY: { PostQuitMessage(0);

// Завершаем работу с DDEML DDEClientClose(hConv);

return 0; } default: break; } return DefWindowProc(hwnd, msg, wParam, lParam);
}

Обработчик сообщения WM_CREATE при инициализации главного окна приложения вызывает функцию DDEClientOpen, определенную в файле ddemlcf.cpp (листинг 3.7). Эта функция регистрирует приложение в библиотеке DDEML и пытается создать канал связи с сервером.

Если канал связи создать не удалось, приложение DDEMLCL делает вывод о том, что сервер не запущен, и предлагает пользователю запустить его. Запуск выполняется при помощи функции WinExec. После удачного запуска сервера делается еще одна попытка создать канал связи.

Когда пользователь выбирает из меню "Action" строку "Send Filename", приложение вызывает функцию DDESend, определенную в файле ddemlcf.cpp. Этой функции передается идентификатор созданного канала связи и текстовая строка "c:\\nicebmp\\sky.bmp". Функция DDESend передаст строку серверу, который отобразит ее на экране.

Если пользователь выбирает из меню "Action" строку "Get Server Version", вызывается функция DDEReceive, также определенная в файле ddemlcf.cpp. Этой функции помимо идентификатора канала связи передается адрес и размер буфера, в который нужно записать принятую информацию. После приема данные отображаются на экране в виде текстовой строки с помощью функции MessageBox.

Когда приложение DDEMLCL завершает свою работу, вызывается функция DDEClientClose, закрывающая канал и освобождающая связанные с ним ресурсы.

В файле ddemlcf.cpp (листинг 3.7) собраны все функции, имеющие отношение к DDEML.


Содержание раздела