MFC stands for Microsoft Foundation Classes.
Keywords: GUI, controls, interaction, resize, dialog.
Warning! This will work only if app isn't minimized to tray. However, you may apply a genius solution based on Mutex.
In CYourApp::InitInstance() call EnumWindows(static_member_func_pointer, (LPARAM)this)
and if it returns FALSE, then quit the app, because another instance is already running.
class CYourApp { private: // - Prevent from launching second instance of the app CString m_str_title; HWND m_hwnd_double; public: static BOOL CALLBACK wnd_comparator(HWND hwnd, LPARAM lParam); ... }; BOOL CYourApp::InitInstance() { ... // - Prevent from second instance of the app m_str_title = CRegistry::Ref().AppTitle(); if (!EnumWindows(&CTEXTApp::wnd_comparator, (LPARAM)this)) { ::SetForegroundWindow(m_hwnd_double); return FALSE; } ... } BOOL CALLBACK CYourApp::wnd_comparator(HWND hwnd, LPARAM lParam) { CYourApp* pThis = reinterpret_cast(lParam); CString strTitle; CWnd::FromHandle(hwnd)->GetWindowText(strTitle); if (strTitle.Find(pThis->m_str_title) >= 0) { pThis->m_hwnd_double = hwnd; return FALSE; //- Found existing instance. Quit searching loop. } return TRUE; // - Continue enumerating. }
Here is how you re-name app. In application's constructor you release previous string value and allocate a new one:
if (m_pszAppName) { free((void*)m_pszAppName); } m_pszAppName = _tcsdup(_T("Whatever it is you like -- put it here"));
ASSERT() is tricky: it's useful, but incorrect usage may cause painful debugging. To avoid any problems a single fact about ASSERT() must be known: in RELEASE version of an application all the code inside it is CUT OUT. So, if you put a function call into the macros to make sure it has completed successfully, in release version you'll get this function call CUT OUT. There won't be a call to function. We wanted to check that the function worked well, but instead we got our code cut out.
So, don't put any crucial code into the macros (like call to a function) because in release version you'll get it cut out.
- Region based shaping (very simple and cool) - flipcode.
- WinAmp skin technique http://www.codeproject.com/KB/dialog/winampwnd.aspx
Here is a little digest (scenario) of how to shape dialog in a cute way:
DWORD dwStyle = GetWindowLong(m_hWnd, GWL_STYLE); dwStyle &= ~(WS_CAPTION | WS_SIZEBOX); SetWindowLong(m_hWnd, GWL_STYLE, dwStyle); InvalidateRect(NULL, TRUE);
HRGN rgn_result, rgn_tmp; DWORD p=0; for (WORD y=0; y < wBmpHeight; y++) { for (WORD x=0; x < wBmpWidth; x++) { BYTE jBlue = pPixels[p]; if (jBlue == 0xff) { // remove transparent color from region rgn_tmp = CreateRectRgn(x, y, x+1, y+1); CombineRgn(rgn_result, rgn_result, rgn_tmp, RGN_XOR); DeleteObject(rgn_tmp); } // next pixel p += 3; } }
SetWindowRgn(rgn_result, TRUE);
1. Right-click upon app-resource.rc; 2. choose Resource symbols; 3. add several ids like ID_INDICATOR_XXX; 4. add dialog's member "CStatusBar m_bar"; 5. add the following array into dialog's cpp file: #define STATUS_BAR_SECTIONS 2 static UINT BASED_CODE indicators[STATUS_BAR_SECTIONS] = { ID_INDICATOR_TXT, ID_INDICATOR_PROGRESSBAR }; 6. into OnInitDialog add this: m_status_bar.Create(this); m_status_bar.SetIndicators(indicators, STATUS_BAR_SECTIONS); CRect rect; GetClientRect(&rect); m_bar.SetPaneInfo(0, ID_INDICATOR_TXT, SBPS_NORMAL, 100); m_bar.SetPaneInfo(1, ID_INDICATOR_PROGRESSBAR, SBPS_STRETCH, 0); RepositionBars( AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, ID_INDICATOR_PROGRESSBAR); m_status_bar.SetPaneText(0, _T("Ready"));
#pragma warning(push) #pragma warning(disable : 4192) //IConvertImage #import "libid:B6D80AF6-B6D4-411A-BFD6-77C1613F511F" named_guids no_namespace raw_interfaces_only #pragma warning(pop)
bool CFileSystem::BrowseFolderDlg(CString& strFolder, UINT nStrID/*=0*/) { CString strTitle; if (nStrID == 0) strTitle = _T(""); else strTitle.LoadString(nStrID); TCHAR path[MAX_PATH]; BROWSEINFO bi = { 0 }; bi.lpszTitle = strTitle; LPITEMIDLIST pidl = SHBrowseForFolder ( &bi ); if ( pidl != 0 ) { SHGetPathFromIDList ( pidl, path ); //SetCurrentDirectory ( path ); //SearchFolder( path ); IMalloc * imalloc = 0; if ( SUCCEEDED( SHGetMalloc ( &imalloc )) ) { imalloc->Free ( pidl ); imalloc->Release ( ); } strFolder.SetString(path); return strFolder.Trim().IsEmpty()? false: true; } return false; }
void CFileSystem::AllFilesFromFolder(CStringArray& rlstFiles, CString& strPath, CString strWildMask) { WIN32_FIND_DATA FindFileData; HANDLE hFind; CString str; rlstFiles.RemoveAll(); SetCurrentDirectory(strPath); hFind = FindFirstFile(strWildMask, &FindFileData); do { if (INVALID_HANDLE_VALUE != hFind) { //Is it a . or .. directory? If it is, skip, or we'll go forever. if (!(wcscmp(FindFileData.cFileName, _T("."))) || !(wcscmp(FindFileData.cFileName, _T("..")))) continue; str.SetString(FindFileData.cFileName); if(str.Trim().IsEmpty()) continue; rlstFiles.Add(strPath + _T("\\") + str); } } while (FindNextFile(hFind, &FindFileData) && INVALID_HANDLE_VALUE!=hFind); FindClose(hFind); }
CString filter(_T("Wave (*.wav)|*.wav||")); CFileDialog dlg( TRUE, _T("wav"), _T(""), OFN_FILEMUSTEXIST, filter, this, sizeof(OPENFILENAME)); dlg.m_ofn.lpstrTitle = _T("Choosing an input wave file"); if (dlg.DoModal() == IDOK) { CString str = dlg.GetPathName().Trim(); m_str_input.SetWindowText(str); }
Ivan Yurlagin,