Приложение DLLCALL
Приложение DLLCALL работает совместно с DLL-библиотекой DLLDemo.DLL, описанной в предыдущем разделе.
Главное окно приложения DLLCALL и меню File показано на рис. 3.7.
Рис. 3.7. Главное окно приложения DLLCALL
Если из меню File выбрать строку Find App Window, на экране появится диалоговая панель Find Application Window, показанная на рис. 3.8.
Рис. 3.8. Диалоговая панель Find Application Window
Здесь в поле Enter application window title to find вы должны ввести заголовок окна приложения. Если приложение с таким заголовком запущено, оно будет найдено, после чего на экране появится соответствующее сообщение (рис. 3.9).
Рис. 3.9. Сообщение о том, что заданное окно найдено
При инициализации DLL-библиотеки, вызванной подключением процесса DLLCALL, на экране возникает сообщение, показанное на рис. 3.10.
Рис. 3.10. Собщение о подключении процесса к DLL-библиотеке
Когда приложение DLLCALL отключается от DLL-библиотеки, на экран выводится сообщение, показанное на рис. 3.11.
Рис. 3.11. Сообщение об отключении процесса от DLL-библиотеки
Главный файл исходных текстов приложения DLLCALL представлен в листинге 3.4.
Листинг 3.4. Файл dlldemo\dllcall\dllcall.c
// ==================================================
// Приложение DLLCall
// Вызов функции из DLL-библиотеки
//
// (С) Фролов А.В., 1996
// Email: frolov@glas.apc.org
// ==================================================
#define STRICT
#include <windows.h>
#include <windowsx.h>
#include "resource.h"
#include "afxres.h"
#include "dllcall.h"
// Определяем тип: указатель на функцию
typedef HWND (WINAPI *MYDLLPROC)(LPSTR);
// Указатель на функцию, расположенную в
// DLL-библиотеке
MYDLLPROC GetAppWindow;
// Буфер для заголовка окна, поиск которого
// будет выполняться
char szWindowTitle[512];
// Идентификатор DLL-библиотеки
HANDLE hDLL;
HINSTANCE hInst;
char szAppName[] = "DLLCallApp";
char szAppTitle[] = "DLL Call Demo";
// -----------------------------------------------------
// Функция WinMain
// -----------------------------------------------------
int APIENTRY
WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc;
HWND hWnd;
MSG msg;
// Сохраняем идентификатор приложения
hInst = hInstance;
// Преверяем, не было ли это приложение запущено ранее
hWnd = FindWindow(szAppName, NULL);
if(hWnd)
{
// Если было, выдвигаем окно приложения на
// передний план
if(IsIconic(hWnd))
ShowWindow(hWnd, SW_RESTORE);
SetForegroundWindow(hWnd);
return FALSE;
}
// Регистрируем класс окна
memset(&wc, 0, sizeof(wc));
wc.cbSize = sizeof(WNDCLASSEX);
wc.hIconSm = LoadImage(hInst,
MAKEINTRESOURCE(IDI_APPICONSM),
IMAGE_ICON, 16, 16, 0);
wc.style = 0;
wc.lpfnWndProc = (WNDPROC)WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInst;
wc.hIcon = LoadImage(hInst,
MAKEINTRESOURCE(IDI_APPICON),
IMAGE_ICON, 32, 32, 0);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
wc.lpszMenuName = MAKEINTRESOURCE(IDR_APPMENU);
wc.lpszClassName = szAppName;
if(!RegisterClassEx(&wc))
if(!RegisterClass((LPWNDCLASS)&wc.style))
return FALSE;
// Создаем главное окно приложения
hWnd = CreateWindow(szAppName, szAppTitle,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
NULL, NULL, hInst, NULL);
if(!hWnd) return(FALSE);
// Отображаем окно и запускаем цикл
// обработки сообщений
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
// -----------------------------------------------------
// Функция WndProc
// -----------------------------------------------------
LRESULT WINAPI
WndProc( HWND hWnd, UINT msg, WPARAM wParam,
LPARAM lParam)
{
switch(msg)
{
HANDLE_MSG(hWnd, WM_COMMAND, WndProc_OnCommand);
HANDLE_MSG(hWnd, WM_DESTROY, WndProc_OnDestroy);
default:
return(DefWindowProc(hWnd, msg, wParam, lParam));
}
}
// -----------------------------------------------------
// Функция WndProc_OnDestroy
// -----------------------------------------------------
#pragma warning(disable: 4098)
void WndProc_OnDestroy(HWND hWnd)
{
PostQuitMessage(0);
return 0L;
}
// -----------------------------------------------------
// Функция WndProc_OnCommand
// -----------------------------------------------------
#pragma warning(disable: 4098)
void WndProc_OnCommand(HWND hWnd, int id,
HWND hwndCtl, UINT codeNotify)
{
switch (id)
{
case ID_FILE_EXIT:
{
// Завершаем работу приложения
PostQuitMessage(0);
return 0L;
break;
}
case ID_FILE_FINDWINDOW:
{
// Отображаем диалоговую панель для ввода
// заголовка главного окна приложения,
// поиск которого будет выполняться
if(DialogBox(hInst, MAKEINTRESOURCE(IDD_DLGFIND),
hWnd, DlgProc))
{
// Первый способ вызова функции из DLL-библиотеки:
// прямой вызов с использованием библиотеки экспорта
/*
// Выполняем поиск окна с заголовком, заданным
// при помощи диалоговой панели
if(FindApplicationWindow(szWindowTitle) != NULL)
MessageBox(NULL, "Application window was found",
szAppTitle, MB_OK | MB_ICONINFORMATION);
else
MessageBox(NULL, "Application window was not found",
szAppTitle, MB_OK | MB_ICONINFORMATION);
*/
// Второй способ вызова функции из DLL-библиотеки:
// загрузка DLL-библиотеки функцией LoadLibrary
// Загружаем DLL-библиотеку
hDLL = LoadLibrary("DLLDEMO.DLL");
// Если библиотека загружена успешно, выполняем
// вызов функции
if(hDLL != NULL)
{
// Получаем адрес нужной нам функции
GetAppWindow =
(MYDLLPROC)GetProcAddress(hDLL,
"FindApplicationWindow");
// Если адрес получен, вызываем функцию
if(GetAppWindow != NULL)
{
// Выполняем поиск окна с заголовком, заданным
// при помощи диалоговой панели
if(GetAppWindow(szWindowTitle) != NULL)
MessageBox(NULL, "Application window was found",
szAppTitle, MB_OK | MB_ICONINFORMATION);
else
MessageBox(NULL,
"Application window was not found",
szAppTitle, MB_OK | MB_ICONINFORMATION);
}
// Освобождаем DLL-библиотеку
FreeLibrary(hDLL);
}
}
break;
}
case ID_HELP_ABOUT:
{
MessageBox(hWnd,
"DLL Call Demo\n"
"(C) Alexandr Frolov, 1996\n"
"Email: frolov@glas.apc.org",
szAppTitle, MB_OK | MB_ICONINFORMATION);
return 0L;
break;
}
default:
break;
}
return FORWARD_WM_COMMAND(hWnd, id, hwndCtl, codeNotify,
DefWindowProc);
}
// -----------------------------------------------------
// Функция DlgProc
// -----------------------------------------------------
LRESULT WINAPI
DlgProc( HWND hdlg, UINT msg, WPARAM wParam,
LPARAM lParam)
{
switch(msg)
{
HANDLE_MSG(hdlg, WM_INITDIALOG, DlgProc_OnInitDialog);
HANDLE_MSG(hdlg, WM_COMMAND, DlgProc_OnCommand);
default:
return FALSE;
}
}
// -----------------------------------------------------
// Функция DlgProc_OnInitDialog
// -----------------------------------------------------
BOOL DlgProc_OnInitDialog(HWND hdlg, HWND hwndFocus,
LPARAM lParam)
{
return TRUE;
}
// -----------------------------------------------------
// Функция DlgProc_OnCommand
// -----------------------------------------------------
#pragma warning(disable: 4098)
void DlgProc_OnCommand(HWND hdlg, int id,
HWND hwndCtl, UINT codeNotify)
{
switch (id)
{
case IDOK:
{
// Если пользователь нажал кнопку OK,
// получаем текст из поля редактирования и
// сохраняем его в глобальном буфере szWindowTitle
GetDlgItemText(hdlg, IDC_EDIT1, szWindowTitle, 512);
// Завершаем работу диалоговой панели
EndDialog(hdlg, 1);
return TRUE;
}
// Если пользователь нажимает кнопку Cancel,
// завершаем работу диалоговой панели
case IDCANCEL:
{
// Завершаем работу диалоговой панели
EndDialog(hdlg, 0);
return TRUE;
}
default:
break;
}
return FALSE;
}
Файл dllcall.h (листинг 3.5) содержит прототипы функций, определенных в приложении DLLCALL.
Листинг 3.5. Файл dlldemo\dllcall\dllcall.h
// -----------------------------------------------------
// Описание функций
// -----------------------------------------------------
LRESULT WINAPI
WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
void WndProc_OnCommand(HWND hWnd, int id,
HWND hwndCtl, UINT codeNotify);
void WndProc_OnDestroy(HWND hWnd);
HWND FindApplicationWindow(LPSTR lpszWindowTitle);
LRESULT WINAPI
DlgProc(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam);
BOOL DlgProc_OnInitDialog(HWND hdlg, HWND hwndFocus,
LPARAM lParam);
void DlgProc_OnCommand(HWND hdlg, int id,
HWND hwndCtl, UINT codeNotify);
В файле dllcall.rc (листинг 3.6) определены ресурсы приложения DLLCALL. Это меню, две пиктограммы и диалоговая панель, а также текстовые строки, которые не используются.
Листинг 3.6. Файл dlldemo\dllcall\dllcall.rc
// Microsoft Developer Studio generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
//////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
//////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
//////////////////////////////////////////////////////////////
// Russian resources
#if !defined(AFX_RESOURCE_DLL) defined(AFX_TARG_RUS)
#ifdef _WIN32
LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT
#pragma code_page(1251)
#endif //_WIN32
//////////////////////////////////////////////////////////////
//
// Menu
//
IDR_APPMENU MENU DISCARDABLE
BEGIN
POPUP "&File"
BEGIN
MENUITEM "F&ind App Window", ID_FILE_FINDWINDOW
MENUITEM SEPARATOR
MENUITEM "E&xit", ID_FILE_EXIT
END
POPUP "&Help"
BEGIN
MENUITEM "&About...", ID_HELP_ABOUT
END
END
#ifdef APSTUDIO_INVOKED
//////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE DISCARDABLE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE DISCARDABLE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE DISCARDABLE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
//////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure
// application icon
// remains consistent on all systems.
IDI_APPICON ICON DISCARDABLE "Dllcall.ico"
IDI_APPICONSM ICON DISCARDABLE "Dllcalsm.ico"
//////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_DLGFIND DIALOG DISCARDABLE 0, 0, 247, 74
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Find Application Window"
FONT 8, "MS Sans Serif"
BEGIN
EDITTEXT IDC_EDIT1,21,31,152,16,ES_AUTOHSCROLL
DEFPUSHBUTTON "OK",IDOK,190,7,50,14
PUSHBUTTON "Cancel",IDCANCEL,190,24,50,14
GROUPBOX "Enter application window title to find",
IDC_STATIC,13,13,167,49
END
//////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO DISCARDABLE
BEGIN
IDD_DLGFIND, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 240
TOPMARGIN, 7
BOTTOMMARGIN, 67
END
END
#endif // APSTUDIO_INVOKED
#endif // Russian resources
//////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
//////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
//////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED
Файл resource.h (листинг 3.7) содержит определения констант для файла описания ресурсов приложения.
Листинг 3.7. Файл dlldemo\dllcall\resource.h
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by DLLCall.rc
//
#define IDR_MENU1 101
#define IDR_APPMENU 101
#define IDI_APPICON 102
#define IDI_APPICONSM 103
#define IDD_DLGFIND 104
#define IDC_EDIT1 1000
#define ID_FILE_EXIT 40001
#define ID_HELP_ABOUT 40002
#define ID_FILE_FINDWINDOW 40003
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 105
#define _APS_NEXT_COMMAND_VALUE 40004
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
Рассмотрим исходные тексты приложения DLLCALL.