// ==================================================
// Приложение 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;
}
