Выбрать главу

int WINAPI WinMain (HINSTANCE hInst, HINSTANCE hPrevInst, char* cmdParam, int cmdShow) {

 _set_new_handler(&NewHandler);

 // Using exceptions here helps debugging your program

 // and protects from unexpected incidents.

 try {

  // Create top window class

  TopWinClass topWinClass(ID_MAIN, hInst, MainWndProc);

  // Is there a running instance of this program?

  HWND hwndOther = topWinClass.GetRunningWindow ();

  if (hwndOther != 0) {

   ::SetForegroundWindow(hwndOther);

   if (::IsIconic(hwndOther)) ::ShowWindow(hwndOther, SW_RESTORE);

   return 0;

  }

  topWinClass.Register();

  // Create top window

  ResString caption(hInst, ID_CAPTION);

  TopWinMaker topWin(topWinClass, caption);

  topWin.Create();

  topWin.Show(cmdShow);

  // The main message loop

  MSG msg;

  int status;

  while ((status = ::GetMessage(&msg, 0, 0, 0)) != 0) {

   if (status == –1) return –1;

   ::TranslateMessage(&msg);

   ::DispatchMessage(&msg);

  }

  return msg.wParam;

 }  catch(WinException e) {

  char buf [50];

  wsprintf(buf, "%s, Error %d", e.GetMessage(), e.GetError());

  ::MessageBox(0, buf, "Exception", MB_ICONEXCLAMATION | MB_OK);

 }

 catch (…) {

  ::MessageBox(0, "Unknown", "Exception", MB_ICONEXCLAMATION | MB_OK);

 }

 return 0;

}

WinClass

Давайте, рассмотрим WinClass. Он инкапсулирует предопределенную в Windows структуру WNDCLASSEX и обеспечивает приемлемые значения по умолчанию для всех ее полей. Этот класс получен из более простого класса WinSimpleClass, который Вы могли бы использовать, чтобы инкапсулировать некоторые встроенные в Windows классы (такие как кнопки, списки просмотров, и т.д.).

Я обеспечил примеры методами, которые могут использоваться, чтобы перестроить значения, устанавливаемые по умолчанию. Например, SetBgSysColor изменяет заданный по умолчанию цвет заднего фона окна к одному из предопределенных цветов системы. Метод SetResIcons загружает соответствующие иконки из ресурсов и присоединяетих к оконному классу. Эти иконки затем появятся в верхнем левом углу основного окна и на панели задач Windows.

TopWinClass наследует от WinClass и использует этот метод. Он также подцепляет меню в вершине оконного класса.

class WinSimpleClass {

public:

 WinSimpleClass(char const * name, HINSTANCE hInst) : _name (name), _hInstance (hInst) {}

 WinSimpleClass (int resId, HINSTANCE hInst);

 char const* GetName() const { return _name.c_str (); }

 HINSTANCE GetInstance() const { return _hInstance; }

 HWND GetRunningWindow();

protected:

 HINSTANCE _hInstance;

 std::string _name;

};

WinSimpleClass::WinSimpleClass(int resid, hinstance hinst) : _hInstance (hInst) {

 ResString resStr (hInst, resId);

 _name = resStr;

}

HWND WinSimpleClass::GetRunningWindow () {

 HWND hwnd = ::FindWindow(getname(), 0);

 if (::IsWindow(hwnd)) {

  HWND hwndPopup = ::GetLastActivePopup(hwnd);

  if (::IsWindow(hwndpopup)) hwnd = hwndPopup;

 } else hwnd = 0;

 return hwnd;

}

class WinClass: public WinSimpleClass {

public:

 WinClass(char const* className, HINSTANCE hInst, WNDPROC wndProc);

 WinClass(int resId, HINSTANCE hInst, WNDPROC wndProc);

 void SetBgSysColor (int sysColor) {

  _class.hbrBackground = reinterpret_cast<HBRUSH> (sysColor + 1);

 }

 void SetResIcons(int resId);

 void Register();

protected:

 void SetDefaults();

 WNDCLASSEX _class;

};

WinClass::WinClass(char const * classname, HINSTANCE hInst, WNDPROC wndProc) : WinSimpleClass (className, hInst) {

 _class.lpfnWndProc = wndProc;

 SetDefaults();

}

WinClass::WinClass(int resid, hinstance hinst, wndproc wndproc) : WinSimpleClass (resId, hInst) {

 _class.lpfnWndProc = wndProc;

 SetDefaults();

}

void WinClass::SetDefaults () {

 // Provide reasonable default values

 _class.cbSize = sizeof (WNDCLASSEX);

 _class.style = 0;

 _class.lpszClassName = GetName();

 _class.hInstance = GetInstance();

 _class.hIcon = 0;

 _class.hIconSm = 0;

 _class.lpszMenuName = 0;

 _class.cbClsExtra = 0;

 _class.cbWndExtra = 0;

 _class.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW + 1);

 _class.hCursor = ::LoadCursor(0, IDC_ARROW);

}

void WinClass::SetResIcons (int resid) {

 _class.hIcon = reinterpret_cast<HICON>(::LoadImage(_class.hInstance, MAKEINTRESOURCE(resId), IMAGE_ICON, ::GetSystemMetrics(sm_cxicon), ::GetSystemMetrics(sm_cyicon), 0));

 // Small icon can be loaded from the same resource

 _class.hIconSm = reinterpret_cast<HICON>(::LoadImage(_class.hInstance, MAKEINTRESOURCE(resId), IMAGE_ICON, :: GetSystemMetrics(sm_cxsmicon), ::GetSystemMetrics(sm_cysmicon), 0));

}

void WinClass::Register () {

 if (::RegisterClassEx(&_class) == 0) throw WinException("Internal error: RegisterClassEx failed.");

}

class TopWinClass: public WinClass {

public:

 TopWinClass(int resId, HINSTANCE hInst, WNDPROC wndProc);

};

TopWinClass::TopWinClass(int resid, HINSTANCE hInst, WNDPROC wndProc) : WinClass (resId, hInst, wndProc) {