
/*
coolbar.exe - demonstrates IE style toolbar and standard file open dialog
Copyright (C) 2000  Antti Markus (antti@pld.ttu.ee)

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/

#define STRICT
#define WIN32_LEAN_AND_MEAN

#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include <commdlg.h>
#include <string.h>
#include <stdlib.h>

#include "winclass.h"
#include "resource.h"
#ifdef __GNUC__
#include "gnu.h"
#endif

#ifndef RBBS_GRIPPERALWAYS
#define RBBS_GRIPPERALWAYS  128
#endif

//*************************************************************
//  CONSTANTS, KONSTANDID
//*************************************************************

#define MAXBUTTONS 11
#define NUMBUTTONS 3

//tööriistariba nuppude info
//toolbar button info
TBBUTTON tbButtons[] = {
	{STD_FILENEW,  IDM_NEW,  TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0},
	{STD_FILEOPEN, IDM_OPEN, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0},
	{STD_FILESAVE, IDM_SAVE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0},
};

const char* pClassName="TTWin32CoolbarEx";

//*************************************************************
//  GLOBAL VARIABLES, GLOBAALSED MUUTUJAD
//*************************************************************

HINSTANCE hMainInst=0;  //instance of the application
HWND hMainWnd=0;        //põhiakna handle
                        //application main window handle
HWND hRebarWnd=0;       //rebar window handle
HWND hWndToolBar=0;     //tööriistariba handle
                        //toolbar window handle
int cxSmIcon, cySmIcon; //väikese ikooni (reeglina 16x16) mõõdud
                        //small icon dimensions
int nIsToolbar=1;       //kas tööriistariba on nähtav?
                        //is toolbar visible?

//*************************************************************
//  FUNCTIONS, FUNKTSIOONID
//*************************************************************

//entry point for a windows program
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pArgs, int nHow);

//main window callback function
LRESULT CALLBACK WindowFunc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

//teateid töötlevad funktsioonid
//message handler functions for the main window
BOOL OnCreate(HWND hwnd, LPCREATESTRUCT lpCreateStruct);
void OnSize(HWND hwnd, UINT state, int cx, int cy);
void OnCommand(HWND hwnd, WORD id, HWND hwndCtl, UINT codeNotify);
void OnDestroy(HWND hwnd);
long OnNotify(HWND hwnd, int id, LPNMHDR pnmh);
void OnGetMinMaxInfo(HWND hwnd, LPMINMAXINFO lpMinMaxInfo);

//kuvab faili avamise dialoogi
//diplays file open dialog
void DoFileDialog(HWND hOwnerWnd);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pArgs, int nHow)
{
  //CS_HREDRAW | CS_VREDRAW style causes annoying flicker when resizing the window
  TWindowClass WinClass(/*CS_HREDRAW | CS_VREDRAW*/0,
                        WindowFunc, hInstance,
                        LoadIcon(NULL, IDI_APPLICATION),
                        LoadIcon(NULL, IDI_APPLICATION),
                        (HBRUSH)GetStockObject(WHITE_BRUSH),
                        IDR_MENU, pClassName);
  if(!WinClass.Register())
    return 0;

  hMainInst=hInstance;

  hMainWnd=CreateWindow(pClassName, "Coolbar example",
                        WS_OVERLAPPEDWINDOW,
                        CW_USEDEFAULT, CW_USEDEFAULT,
                        CW_USEDEFAULT, CW_USEDEFAULT,
                        NULL, NULL, hInstance, NULL);

  ShowWindow(hMainWnd, nHow);
  UpdateWindow(hMainWnd);

  MSG Message;
  while(GetMessage(&Message, NULL, 0, 0))
  {
    TranslateMessage(&Message);
    DispatchMessage(&Message);
  }
  return Message.wParam;
}

LRESULT CALLBACK WindowFunc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
  switch(msg)
  {
    HANDLE_MSG(hwnd, WM_CREATE, OnCreate);
    HANDLE_MSG(hwnd, WM_DESTROY, OnDestroy);
    HANDLE_MSG(hwnd, WM_COMMAND, OnCommand);
    HANDLE_MSG(hwnd, WM_NOTIFY, OnNotify);
    HANDLE_MSG(hwnd, WM_GETMINMAXINFO, OnGetMinMaxInfo);
    HANDLE_MSG(hwnd, WM_SIZE, OnSize);
    default:  //all other messages are handled by default
      return DefWindowProc(hwnd, msg, wParam, lParam);
  }
  return 0;
}

BOOL OnCreate(HWND hwnd, LPCREATESTRUCT lpCreateStruct)
{
  INITCOMMONCONTROLSEX InitStruct;
  InitStruct.dwSize=sizeof(INITCOMMONCONTROLSEX);
  InitStruct.dwICC=ICC_BAR_CLASSES | ICC_COOL_CLASSES;

  if(!(InitCommonControlsEx(&InitStruct)))
  {
    MessageBox((HWND)NULL, "InitCommonControlsEx failed", "Error", MB_OK);
    return FALSE;
  }

  //leiame väikeste ikoonide mõõdud
  //get small icon dimensions
  cxSmIcon=GetSystemMetrics(SM_CXSMICON);
  cySmIcon=GetSystemMetrics(SM_CYSMICON);

  RECT rClient;
  GetClientRect(hwnd, &rClient);

  //loome rebar'i
  //create rebar
  hRebarWnd=CreateWindowEx(0, REBARCLASSNAME, NULL,
                           WS_VISIBLE | WS_BORDER | WS_CHILD | WS_CLIPCHILDREN |
                           WS_CLIPSIBLINGS | CCS_NODIVIDER | CCS_NOPARENTALIGN |
				                   RBS_VARHEIGHT | RBS_BANDBORDERS,
                           0, 0, rClient.right, 10,
				                   hwnd,
				                   (HMENU)NULL,
				                   hMainInst,
				                   (LPVOID)NULL);
  if(!hRebarWnd)
  {
    MessageBox((HWND)NULL, "Rebar creation failed", "Error", MB_OK);
    return FALSE;
  }

  //loome tööriistariba
  //create toolbar
  hWndToolBar=CreateToolbarEx(hRebarWnd,
                              WS_CHILD | WS_VISIBLE | WS_CHILD | 
                              TBSTYLE_TOOLTIPS | TBSTYLE_FLAT |
                              CCS_NODIVIDER | CCS_NORESIZE | CCS_NOPARENTALIGN,
                              IDR_TOOLBAR, MAXBUTTONS, 
                              (HINSTANCE)HINST_COMMCTRL, IDB_STD_SMALL_COLOR,
                              (LPCTBBUTTON)&tbButtons, NUMBUTTONS, 
                              cxSmIcon, cySmIcon, 
                              cxSmIcon, cySmIcon, 
                              sizeof (TBBUTTON));

	if (hWndToolBar == NULL )
	{
		MessageBox ((HWND)NULL, TEXT("Toolbar not created!"), NULL, MB_OK );
    return FALSE;
	}

	REBARBANDINFO rbBand;

  //algväärtustame rebar'i ribade info
	//Initialize REBARBANDINFO for all rebar bands

	rbBand.cbSize = sizeof(REBARBANDINFO);
	rbBand.fMask = RBBIM_COLORS |	    // clrFore and clrBack are valid
		             RBBIM_CHILD |			// hwndChild is valid
		             RBBIM_CHILDSIZE |	// cxMinChild and cyMinChild are valid
		             RBBIM_STYLE |			// fStyle is valid
		             RBBIM_ID;					// wID is valid
	rbBand.clrFore = GetSysColor(COLOR_BTNTEXT);
	rbBand.clrBack = GetSysColor(COLOR_BTNFACE);

  //fStyle peaks sisaldama väärtust RBBS_GRIPPERALWAYS
  //vastasel juhul võib juhtuda, et gripperit ei kuvata
  //(oleneb comctl32.dll versioonist)
  //fStyle should include RBBS_GRIPPERALWAYS
  //otherwise gripper may or may not be displayed
  //(depends on the version number of the comctl32.dll)
	rbBand.fStyle = RBBS_NOVERT |	      // do not display in vertical orientation
		              RBBS_CHILDEDGE | 
                  RBBS_GRIPPERALWAYS; //always display gripper

	rbBand.hwndChild = hWndToolBar;
	rbBand.wID = IDR_TOOLBAR;
	rbBand.cxMinChild = rClient.right >> 1;       //0.5 x client area width
	rbBand.cyMinChild = cySmIcon+(cySmIcon >> 1); //1.5 x cySmIcon

  //lisa riba rebar'i
	// Insert band into rebar
	SendMessage(hRebarWnd, RB_INSERTBAND, (UINT) -1, (LPARAM) (LPREBARBANDINFO) &rbBand);

  return TRUE;
}

void OnDestroy(HWND hwnd)
{
  if(hWndToolBar)
    DestroyWindow(hWndToolBar);
  if(hRebarWnd)
    DestroyWindow(hRebarWnd);
  PostQuitMessage(0);
}

void OnCommand(HWND hwnd, WORD id, HWND hwndCtl, UINT codeNotify)
{
  switch(id)
  {
    case IDM_SAVE:
      break;

    case IDM_NEW:
      break;

    case IDM_OPEN:
      DoFileDialog(hwnd);
      break;

    case ID_OPTIONS_SHOWTOOLBAR:
    {
      HMENU hOptionsMenu=GetMenu(hwnd);
      if(nIsToolbar)
      {
        CheckMenuItem(GetSubMenu(hOptionsMenu, 1), 0, MF_BYPOSITION | MF_UNCHECKED);
        nIsToolbar=0;
        ShowWindow(hRebarWnd, FALSE);
      }
      else
      {
        CheckMenuItem(GetSubMenu(hOptionsMenu, 1), 0, MF_BYPOSITION | MF_CHECKED);
        nIsToolbar=1;
        ShowWindow(hRebarWnd, TRUE);
      }
      break;
    }

    case IDM_EXIT:
      DestroyWindow(hwnd);
      break;
  }
}

long OnNotify(HWND hwnd, int id, LPNMHDR pnmh)
{
  switch(pnmh->code)
  {
    //kui tooltip tahab teksti näidata
    //if tooltip wants to display text
    case TTN_NEEDTEXT:
    {
      LPTOOLTIPTEXT pttext=(LPTOOLTIPTEXT)pnmh;
      switch(id)
      {
        case IDM_NEW:
        {
          pttext->lpszText="Create new document";
          break;
        }

        case IDM_OPEN:
        {
          pttext->lpszText="Open a document";
          break;
        }

        case IDM_SAVE:
        {
          pttext->lpszText="Save a document";
          break;
        }
      }
      break;
    }
  }
  return 0;
}

void OnSize(HWND hwnd, UINT state, int cx, int cy)
{
  RECT rc;
  GetWindowRect(hRebarWnd, &rc);
  MoveWindow(hRebarWnd, 0, 0, cx, rc.bottom-rc.top, TRUE);  
}

void OnGetMinMaxInfo(HWND hwnd, LPMINMAXINFO lpMinMaxInfo)
{
  //esimene kord kutsutakse seda funktsiooni välja
  //enne, kui hRebarWnd mingi mõistliku väärtuse saab
  //this function is called before hRebarWnd is assigned
  //some reasonable value
  if(hRebarWnd)
  {
    //akna min kõrgus jätab toolbar'i nähtavale
    //window's min height leaves some room for the toolbar
    RECT rRebar;
    GetWindowRect(hRebarWnd, &rRebar);
    WORD wMinHeight=GetSystemMetrics(SM_CYMENU)+GetSystemMetrics(SM_CYMINTRACK);
    if(nIsToolbar)
      wMinHeight+=rRebar.bottom-rRebar.top;
    if(lpMinMaxInfo->ptMinTrackSize.y < wMinHeight)
      lpMinMaxInfo->ptMinTrackSize.y = wMinHeight;
  }
}

void DoFileDialog(HWND hOwnerWnd)
{
  char pFilter[]="Text Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0\0";

  OPENFILENAME ofn;

  ofn.lStructSize=sizeof(OPENFILENAME);
  ofn.hwndOwner=hOwnerWnd;
  ofn.hInstance=hMainInst;
  ofn.lpstrFilter=pFilter;
  ofn.lpstrCustomFilter=0;
  ofn.nMaxCustFilter=0;
  ofn.nFilterIndex=0;
  ofn.lpstrFile=0;
  ofn.nMaxFile=_MAX_PATH;
  ofn.lpstrFileTitle=0;
  ofn.nMaxFileTitle=_MAX_FNAME+_MAX_EXT;
  ofn.lpstrInitialDir=0;
  ofn.lpstrTitle=0;
  ofn.Flags=OFN_HIDEREADONLY | OFN_CREATEPROMPT;
  ofn.nFileOffset=0;
  ofn.nFileExtension=0;
  ofn.lpstrDefExt="txt";
  ofn.lCustData=0L;
  ofn.lpfnHook=0;
  ofn.lpTemplateName=0;

  BOOL bRes=GetOpenFileName(&ofn);
}
