www.pudn.com > VC写的MP3播放器源代码.zip > ITAPI.cpp
///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// // // $NoKeywords: $ #include "stdafx.h" #include "ITAPI.h" #includeusing namespace ITCLIB; #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif // Defined in WINCORE.CPP extern HWND AFXAPI AfxGetParentOwner(HWND hWnd); ///////////////////////////////////////////////////////////////////////////// // Static helper functions static void PrettyString(CString& strValue, const int MAX_LEN) { strValue.TrimLeft(); strValue.TrimRight(); // To make the output pretty we want to try to break the // line at spaces or punctuation. We will split the block // into chunks of MAX_LEN and try to find a place // near the end of the block where we can split it. if (strValue.GetLength() > MAX_LEN) { CString strNewData; LPTSTR pszEnd = strValue.GetBuffer(0); while (lstrlen(pszEnd) > MAX_LEN) { LPTSTR pszBegin = pszEnd; // Start from the end of the block // and try to break the line somewhere. pszEnd += MAX_LEN - 1; while (pszEnd != pszBegin) { if (*pszEnd == _T('\r') || *pszEnd == _T('\n')) { TCHAR tch = *pszEnd; *pszEnd = '\0'; strNewData += pszBegin; strNewData += tch; *pszEnd = tch; break; } else if (*pszEnd == _T(' ')) { TCHAR tch = *pszEnd; *pszEnd = '\0'; strNewData += pszBegin; strNewData += _T('\n'); *pszEnd = tch; break; } else if (*pszEnd == _T(',')) { TCHAR tch = *pszEnd; *pszEnd = '\0'; strNewData += pszBegin; strNewData += _T(','); strNewData += _T('\n'); *pszEnd = tch; break; } else if (*pszEnd == _T(';')) { TCHAR tch = *pszEnd; *pszEnd = '\0'; strNewData += pszBegin; strNewData += _T(';'); strNewData += _T('\n'); *pszEnd = tch; break; } pszEnd--; } if (pszEnd == pszBegin) { strNewData += *pszEnd; } pszEnd++; } strNewData += pszEnd; strValue.ReleaseBuffer(); strValue = strNewData; } } static LPCTSTR TrimLeft(LPTSTR lpszSrc) { // find first non-space character LPCTSTR lpsz = lpszSrc; while (_istspace(*lpsz)) lpsz = _tcsinc(lpsz); memmove(lpszSrc, lpsz, (lstrlen(lpsz)+1)*sizeof(TCHAR)); return lpszSrc; } static LPCTSTR TrimRight(LPTSTR lpszSrc) { // find beginning of trailing spaces by starting at beginning (DBCS aware) LPTSTR lpsz = lpszSrc; LPTSTR lpszLast = NULL; while (*lpsz != '\0') { if (_istspace(*lpsz)) { if (lpszLast == NULL) lpszLast = lpsz; } else lpszLast = NULL; lpsz = _tcsinc(lpsz); } if (lpszLast != NULL) { // truncate at trailing space start *lpszLast = '\0'; } return lpszSrc; } ///////////////////////////////////////////////////////////////////////////// // // @doc EXTERNAL API // @func This function uses to find the module // of the specified resource. If the module is found, // is called to get a handle to the resource and is called // to load the resource. Finally is called to lock the // resource in memory. If any of these functions fail, a // object is thrown. // // It is not necessary to unlock resources that are locked by this function. // // @parm A pointer to resource name created by MAKEINTRESOURCE. // @parm A pointer to a resource type. For more information see the Win32 // documentation on the function. // @parm A pointer to a DWORD containing the size of the resource; can be NULL. // @parm A pointer to an HINSTANCE containing the module handle of the resource; can be NULL. // @parm A pointer to an HRSRC containing the handle of the resource; can be NULL. // // @rdesc A pointer to the first byte of the resource. // // @comm This function is in the ITCLIB namespace. LPVOID ITCLIB::FindLoadAndLockResource(LPCTSTR lpName, LPCTSTR lpType, DWORD* pdwSizeof, HINSTANCE* phModule, HRSRC* phResInfo) { ASSERT(lpName); ASSERT(lpType); if (phModule) *phModule = NULL; if (phResInfo) *phResInfo = NULL; if (pdwSizeof) *pdwSizeof = 0; HINSTANCE hModule = ::AfxFindResourceHandle(lpName, lpType); if (!hModule) { TRACE("Failed to find a module with the resource '%s' of the type '%s'\n", lpName, lpType); AfxThrowResourceException(); } HRSRC hResInfo = ::FindResource(hModule, lpName, lpType); if (!hResInfo) { TRACE("Failed to find the resource '%s' of the type '%s'\n", lpName, lpType); AfxThrowResourceException(); } HGLOBAL hResData = ::LoadResource(hModule, hResInfo); if (!hResData) { TRACE("Failed to load the resource '%s' of the type '%s'\n", lpName, lpType); AfxThrowResourceException(); } LPVOID lpVoid = ::LockResource(hResData); if (!lpVoid) { TRACE("Failed to lock the resource '%s' of the type '%s'\n", lpName, lpType); AfxThrowResourceException(); } if (phModule) *phModule = hModule; if (phResInfo) *phResInfo = hResInfo; if (pdwSizeof) *pdwSizeof = ::SizeofResource(hModule, hResInfo); return lpVoid; } // @func Determines the current screen dimensions using the // SM_CXSCREEN and SM_CYSCREEN values returned by . // // @rdesc A object with the screen dimensions. // // @comm This function is in the ITCLIB namespace. CSize ITCLIB::GetScreenDimensions() { // g_sysCache.OnUpdateMetrics(); return CSize(0,0); } // @func This function uses the to get a string // description of the error codes returned by the // function. // // @syntax CString GetLastErrorMessage(); // @syntax CString GetLastErrorMessage(DWORD dwLastError); // // @parm DWORD | dwLastError | An error code returned by . // // @rdesc A string description of the error code. // // @comm The first version of this function calls the second version // of this function with the result of calling . // // This function is in the ITCLIB namespace. CString ITCLIB::GetLastErrorMessage(DWORD dwLastError) { LPVOID lpMessageBuffer = NULL; VERIFY(::FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwLastError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), //The user default language (LPTSTR)&lpMessageBuffer, 0, NULL) != 0); CString strMessage = (LPTSTR)lpMessageBuffer; ::LocalFree(lpMessageBuffer); return strMessage; } CString ITCLIB::GetLastErrorMessage() { return GetLastErrorMessage(::GetLastError()); } // @func This function calls to determine the last // network error code. This function will only return a valid result // if returns ERROR_EXTENDED_ERROR. // // @rdesc The error code reported by the network provider. The error code // is specific to the network provider // // @comm This function is in the ITCLIB namespace. DWORD ITCLIB::GetLastWNetError() { DWORD dwLastWNetError = NO_ERROR; if (::GetLastError() == ERROR_EXTENDED_ERROR) { // ::WNetGetLastError(&dwLastWNetError, szErrorMessage, // MAX_ERROR_LEN, szProviderName, // MAX_PROVIDER_LEN); } return dwLastWNetError; } // @func This function uses the to create a string // description of the error codes returned by the // function. // // @syntax CString GetLastWNetErrorMessage(); // @syntax CString GetLastWNetErrorMessage(DWORD dwLastError); // // @parm DWORD | dwLastError | An error code returned by . // // @rdesc A string description of the error code. // // @comm The first version of this function calls the second version // of this function with the result of calling . // // This function is in the ITCLIB namespace. CString ITCLIB::GetLastWNetErrorMessage(DWORD dwLastError) { CString strErrorMessage; if (dwLastError == ERROR_EXTENDED_ERROR) { /* if (WNetGetLastError(&dwLastWNetError, szErrorMessage, MAX_ERROR_LEN, szProviderName, MAX_PROVIDER_LEN) == NO_ERROR) { if (strlen(szProviderName) > 0) { strErrorMessage.Format("%s [Provider %s Network Error %d]", szErrorMessage, szProviderName, dwLastWNetError); } else { strErrorMessage.Format("%s [Network Error %d]", szErrorMessage, dwLastWNetError); } } else {*/ strErrorMessage.Format("An unknown network error occured."); //} } else { strErrorMessage.Format("The last error was not an extended error."); } return strErrorMessage; } CString ITCLIB::GetLastWNetErrorMessage() { return GetLastWNetErrorMessage(ITCLIB::GetLastWNetError()); } // @func When you call the Win32 , the top and left // coordinates are always (0,0). This is useless when you need to call // a function like the Win32 . This function // returns a rectangle with coordinates that can be passed to . // // @parm HWND | hWnd | The window handle of the window. // @parm CWnd* | pWnd | The of the window. // @parm CRect& | rc | A reference to a object to receive // the coordinates. // // @comm This function is in the ITCLIB namespace. void ITCLIB::GetRealClientRect(HWND hWnd, CRect& rcInParent) { // Returns coordinates that can be passed into MoveWindow rcInParent.SetRectEmpty(); CRect rcWindow; ::GetWindowRect(hWnd, rcWindow); rcInParent = rcWindow; HWND hWndParent = ::GetParent(hWnd); if (hWndParent) { ::ScreenToClient(hWndParent, &(rcInParent.TopLeft())); rcInParent.right = rcInParent.left + rcWindow.Width(); rcInParent.bottom = rcInParent.top + rcWindow.Height(); } } void ITCLIB::GetRealClientRect(CWnd* pWnd, CRect& rcInParent) { ASSERT_POINTER(pWnd, CWnd); GetRealClientRect(pWnd->GetSafeHwnd(), rcInParent); } // @func Sets the focus and sends an EM_SETSEL message to select the // text of the specified edit control. // // @parm The of the window. // // @comm This function is in the ITCLIB namespace. void ITCLIB::SelectWindowText(CWnd* pWnd) { ASSERT_POINTER(pWnd, CWnd); pWnd->SetFocus(); pWnd->SendMessage(EM_SETSEL, 0, -1); } // @func This function peeks into the message queue using // and if there are no messages in the queue, one is posted // using
. // // @parm Identifies the window whose window procedure is to receive the message. // @parm Specifies the message to be posted. // @parm Specifies additional message-specific information. // @parm Specifies additional message-specific information. // // @rdesc Nonzero if successful; otherwise 0. // // @comm This function is in the ITCLIB namespace. BOOL ITCLIB::PostUniqueMessage(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam) { MSG msg; if (!::PeekMessage(&msg, hWnd, nMsg, nMsg, PM_NOREMOVE)) { return ::PostMessage(hWnd, nMsg, wParam, lParam); } return TRUE; } // @func This function appends a string to another string, inserting // an optional prefix if necessary. // // @parm A reference to the string to append to. // @parm The prefix to add before
if
is not empty. // @parm The string to append. If this string is empty,
is unaffected. // // @rdesc A reference to
. // // @comm This function is in the ITCLIB namespace. // // @ex This function could be used to build the WHERE clause of an SQL query. | // // CString strWhere; // // AppendStringWithPrefix(strWhere, " AND ", "ID > 0"); // AppendStringWithPrefix(strWhere, " AND ", "Price > 1.00"); // AppendStringWithPrefix(strWhere, " AND ", "Price < 10.00"); // // ASSERT(strWhere == "ID > 0 AND Price > 1.00 AND Price < 10.00"); // CString& ITCLIB::AppendStringWithPrefix(CString& str, CString strPrefix, CString strAppend) { if (!strAppend.IsEmpty()) { if (!str.IsEmpty()) str += strPrefix; str += strAppend; } return str; } // @func This function splits a string into two pieces using
// as the separator. The resulting strings will be trimmed of whitespace. // If the separator cannot be found, the strings are unaffected. // // @parm The string to split. // @parm The first instance of this character will be the dividing point. // @parm A reference to a
that will contain the left half // of the split. // @parm A reference to a that will contain the right half // of the split. // // @rdesc Nonzero if successful; otherwise 0. // // @comm This function is in the ITCLIB namespace. BOOL ITCLIB::SplitString(const CString& rString, char chSplit, CString& strLeft, CString& strRight) { const int ch = rString.Find(chSplit); const int nLen = rString.GetLength(); // No separator if (ch == -1) return FALSE; strLeft = rString.Left(ch); strRight = rString.Right(nLen - ch - 1); TrimString(strLeft); TrimString(strRight); return TRUE; } // @func Removes the last character from the specified string. // If the string is empty the string is unaffected. // // @parm A reference to a . // // @comm This function is in the ITCLIB namespace. void ITCLIB::RemoveLastChar(CString& rString) { if (!rString.IsEmpty()) { rString.GetBufferSetLength(rString.GetLength()-1); rString.ReleaseBuffer(); } } // @func Replaces the last character of the specified string. // If the string is empty the string is unaffected. // // @parm A reference to a . // @parm The character to replace the last character with. // // @comm This function is in the ITCLIB namespace. void ITCLIB::ReplaceLastChar(CString& rString, TCHAR ch) { if (!rString.IsEmpty()) { rString.SetAt(rString.GetLength()-1, ch); } } // @func Returns the last character in the specified string. // // @parm A reference to a . // // @rdesc The last character in the string or 0 if the string is empty. // // @comm This function is in the ITCLIB namespace. TCHAR ITCLIB::LastChar(CString& rString) { return (!rString.IsEmpty()) ? rString.GetAt(rString.GetLength() - 1) : '\0'; } // @func Returns the first character in the specified string. // // @parm A reference to a . // // @rdesc The first character in the string or 0 if the string is empty. // // @comm This function is in the ITCLIB namespace. TCHAR ITCLIB::FirstChar(CString& rString) { return (!rString.IsEmpty()) ? rString.GetAt(0) : '\0'; } // @func Replaces characters in a string. // // @parm A reference to a . // @parm The character to find and replace. // @parm The character replacement. // // @rdesc The number of characters replaced. // // @comm This function is in the ITCLIB namespace. int ITCLIB::ReplaceChars(CString& string, TCHAR chThis, TCHAR chWith) { int nReplacements = 0; for (int i=0; i < string.GetLength(); i++) { if (string.GetAt(i) == chThis) { string.SetAt(i, chWith); nReplacements++; } } return nReplacements; } // @func Finds the last occurance of the specified substring. // // @parm Null-terminated string to search. // @parm Null-terminated string to search for. // // @rdesc A pointer to the last occurance of the substring or NULL // if the substring cannot be found. // // @comm This function is in the ITCLIB namespace. LPCTSTR ITCLIB::ReverseFindString(LPCTSTR lpszString, LPCTSTR lpszSub) { LPCTSTR lpszFindLast = strstr(lpszString, lpszSub); LPCTSTR lpszFindNext = lpszFindLast; while (lpszFindNext) { lpszFindNext = strstr(lpszFindLast + strlen(lpszSub), lpszSub); if (lpszFindNext) lpszFindLast = lpszFindNext; } return lpszFindLast; } // @func Returns the string after the last occurance of the // specified separator. // // @parm The string to search. // @parm Ths string to search for. // // @rdesc The string after the last occurance of the separator. // // @comm This function is in the ITCLIB namespace. CString ITCLIB::GetStringAfterSeperator(CString strValue, CString strSeperator) { CString strAfter = strValue; LPCTSTR lpszEndOfValue = ReverseFindString(strValue, strSeperator); if (lpszEndOfValue) { strValue = lpszEndOfValue; int nLen = strValue.GetLength(); int nSepLen = strSeperator.GetLength(); strAfter = strValue.Right(nLen - nSepLen); } return strAfter; } #ifdef _DEBUG // @func Outputs a description of the specified window to . // The description can include the window class, its handle value, and // its caption. // // @parm The of the window. // @parm The level of indentation to output before the description. // A tab character will be output for each level. // // @comm This function is in the ITCLIB namespace. void ITCLIB::TraceWindow(CWnd* pWnd, int nLevel) { ASSERT(pWnd != NULL); // Indent for (int i=0; i < nLevel; i++) afxDump << "\t"; CRuntimeClass* pRuntime = pWnd->GetRuntimeClass(); if (pRuntime == NULL) { afxDump << "a window"; } else { afxDump << "a " << pWnd->GetRuntimeClass()->m_lpszClassName; } afxDump << " with HWND"; afxDump << " " << (HWND)*pWnd; CString strLabel; pWnd->GetWindowText(strLabel); if (!strLabel.IsEmpty()) afxDump << " '" << strLabel << "'"; afxDump << "\n"; } // @func This function outputs a description of the specified parent, // its children, and optionally all descendent children using . // // @parm The of the parent window. // @parm If nonzero, all descendent children will be output. // @parm The indentation level; should be 0 when enumerating the parent. // // @comm This function is in the ITCLIB namespace. void ITCLIB::TraceWindowChildren(CWnd* pParentWnd, BOOL bRecursive, int nLevel) { ASSERT_VALID(pParentWnd); if (nLevel == 0) { afxDump << "Enumerating children of "; TraceWindow(pParentWnd, 0); nLevel++; } // Enumerate children for (HWND hWndChild = ::GetTopWindow(*pParentWnd); hWndChild != NULL; hWndChild = ::GetNextWindow(hWndChild, GW_HWNDNEXT)) { CWnd* pChildWnd = CWnd::FromHandle(hWndChild); TraceWindow(pChildWnd, nLevel); if (bRecursive) TraceWindowChildren(pChildWnd, TRUE, nLevel+1); } } #endif // _DEBUG // @func Shows the enables the specified window using and // . If the window is hidden it is automatically // disabled. // // @syntax BOOL ShowAndEnableWindow(HWND hWnd, BOOL bShow, BOOL bEnable); // @syntax BOOL ShowAndEnableWindow(CWnd* pChild, BOOL bShow, BOOL bEnable); // @syntax BOOL ShowAndEnableWindow(CWnd* pParent, UINT nIDC, BOOL bShow, BOOL bEnable); // // @parm HWND | hWnd | The window handle of the window. // @parm CWnd* | pChild | The of the window. // @parm CWnd* | pParent | The of the parent window. // @parm UINT | nIDC | The ID of the child window. // @parm BOOL | bShow | Nonzero to show the window; 0 to hide it. // @parm BOOL | bEnable | Nonzero to enable the window; 0 to disable it. // // @rdesc Nonzero if successful; otherwise 0. // // @comm This function is in the ITCLIB namespace. BOOL ITCLIB::ShowAndEnableWindow(HWND hWnd, BOOL bShow, BOOL bEnable) { BOOL bSuccess = FALSE; // Always disable hidden windows to keep the control from // getting the focus and to disable any acclerators. if (!bShow) bEnable = FALSE; if (hWnd) { ::ShowWindow(hWnd, (bShow) ? SW_SHOW : SW_HIDE); ::EnableWindow(hWnd, bEnable); bSuccess = TRUE; } return bSuccess; } BOOL ITCLIB::ShowAndEnableWindow(CWnd* pChild, BOOL bShow, BOOL bEnable) { if (pChild) return ShowAndEnableWindow(pChild->GetSafeHwnd(), bShow, bEnable); return FALSE; } BOOL ITCLIB::ShowAndEnableWindow(CWnd* pParent, UINT nIDC, BOOL bShow, BOOL bEnable) { ASSERT_VALID(pParent); ASSERT(::IsWindow(*pParent)); if (!pParent || !::IsWindow(*pParent)) { TRACE("The parent window is invalid\n"); return FALSE; } CWnd* pChild = pParent->GetDlgItem(nIDC); if (!pChild) { TRACE("Failed to find a child control with ID %08x\n", nIDC); return FALSE; } return ShowAndEnableWindow(pChild, bShow, bEnable); } // @func This function calls to show and // enable the next sibling window of the specified child. // // @parm The of the parent window. // @parm The ID of the child window. // @parm Nonzero to show the window; 0 to hide it. // @parm Nonzero to enable the window; 0 to disable it. // // @rdesc Nonzero if successful; otherwise 0. // // @comm This function is in the ITCLIB namespace. // // @xref BOOL ITCLIB::ShowNextDialogSibling(CWnd* pParent, UINT nIDC, BOOL bShow, BOOL bEnable) { ASSERT_VALID(pParent); ASSERT(::IsWindow(*pParent)); if (!pParent || !::IsWindow(*pParent)) { TRACE("The parent window is invalid\n"); return FALSE; } CWnd* pChild = pParent->GetDlgItem(nIDC); if (!pChild) { TRACE("Failed to find a child control with ID %08x\n", nIDC); return FALSE; } CWnd* pNext = pChild->GetWindow(GW_HWNDNEXT); if (!pNext) { TRACE("The child control with ID %08x does not have a next sibling\n", nIDC); return FALSE; } return ShowAndEnableWindow(pNext, bShow, bEnable); } // @func This function calls to show and // enable the previous sibling window of the specified child. // // @parm The of the parent window. // @parm The ID of the child window. // @parm Nonzero to show the window; 0 to hide it. // @parm Nonzero to enable the window; 0 to disable it. // // @rdesc Nonzero if successful; otherwise 0. // // @comm This function is in the ITCLIB namespace. // // @xref BOOL ITCLIB::ShowPrevDialogSibling(CWnd* pParent, UINT nIDC, BOOL bShow, BOOL bEnable) { ASSERT_VALID(pParent); ASSERT(::IsWindow(*pParent)); if (!pParent || !::IsWindow(*pParent)) { TRACE("The parent window is invalid\n"); return FALSE; } CWnd* pChild = pParent->GetDlgItem(nIDC); if (!pChild) { TRACE("Failed to find a child control with ID %08x\n", nIDC); return FALSE; } CWnd* pPrev = pChild->GetWindow(GW_HWNDPREV); if (!pPrev) { TRACE("The child control with ID %08x does not have a next sibling\n", nIDC); return FALSE; } return ShowAndEnableWindow(pPrev, bShow, bEnable); } // @func This functions uses to show and enable // dialog controls as well as their associated static controls (usually // used as a label). // // @parm The of the parent window. // @parm The ID of the child window. // @parm Nonzero to show the window; 0 to hide it. // @parm Nonzero to enable the window; 0 to disable it. // @parm Nonzero to automatically change the state of the previous // static control window when necessary. // // @rdesc Nonzero if successful; otherwise 0. // // @comm This function is in the ITCLIB namespace. // // @xref BOOL ITCLIB::ShowDialogControl(CWnd* pParent, UINT nIDC, BOOL bShow, BOOL bEnable, BOOL bSmart) { ASSERT_VALID(pParent); ASSERT(::IsWindow(*pParent)); if (!pParent || !::IsWindow(*pParent)) { TRACE("The parent window is invalid\n"); return FALSE; } CWnd* pChild = pParent->GetDlgItem(nIDC); if (!pChild) { TRACE("Failed to find a child control with ID %08x\n", nIDC); return FALSE; } VERIFY(ShowAndEnableWindow(pChild, bShow, bEnable)); // Setting this to TRUE will cause the immediate // siblings of this child to be hidden if they // match a specific set of criteria. BOOL bHideSiblings = FALSE; if (IsEditControl(*pChild)) { // Definitely edit controls bHideSiblings = TRUE; } else if ((pChild->SendMessage(WM_GETDLGCODE) & DLGC_BUTTON) == 0) { // Assume anything other than buttons are safe bHideSiblings = TRUE; } if (bSmart && bHideSiblings) { CWnd* pPrev = pChild->GetWindow(GW_HWNDPREV); // Hide the label for the edit contol if (pPrev && IsStaticControl(*pPrev)) { VERIFY(ShowAndEnableWindow(pPrev, bShow, bEnable)); } } return TRUE; } // @func Sends a message to the owner of the specified window. A message // is not sent if the window does not have an owner. // // @parm The window handle of the window. // @parm Specifies the message to send. // @parm Specifies additional message-specific information. // @parm Specifies additional message-specific information. // // @rdesc The results of if successful; otherwise -1. // // @comm This function is in the ITCLIB namespace. LRESULT ITCLIB::SendMessageToOwner(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam) { ASSERT(::IsWindow(hWnd)); HWND hwndOwner = AfxGetParentOwner(hWnd); if (!hwndOwner) { TRACE("The specified window does not have an owner\n"); return -1; } return ::SendMessage(hwndOwner, nMsg, wParam, lParam); } // @func This function uses to send a // notification to the owner of a child control. Notification codes // are sent to the parent in a WM_COMMAND message and // notifications are sent in a WM_NOTIFY message. // // @syntax LRESULT SendNotifyToOwner(HWND hWnd, WORD wNotifyCode); // @syntax LRESULT SendNotifyToOwner(HWND hWnd, LPNMHDR pnmh); // @syntax LRESULT SendNotifyToOwner(CWnd* pControl, WORD wNotifyCode); // @syntax LRESULT SendNotifyToOwner(CWnd* pControl, LPNMHDR pnmh); // // @parm HWND | hWnd | The window handle of the window. // @parm CWnd* | pControl | The of the window. // @parm WORD | wNotifyCode | The notification code such as BN_CLICKED. // @parm LPNMHDR | pnmh | A pointer to a structure. // // @rdesc The results of . // // @comm This function is in the ITCLIB namespace. // // @xref LRESULT ITCLIB::SendNotifyToOwner(HWND hWnd, WORD wNotifyCode) { int nCtrlID = ::GetDlgCtrlID(hWnd); WPARAM wParam = MAKEWPARAM(nCtrlID, wNotifyCode); LPARAM lParam = (LPARAM)hWnd; return SendMessageToOwner(hWnd, WM_COMMAND, wParam, lParam); } LRESULT ITCLIB::SendNotifyToOwner(HWND hWnd, LPNMHDR pnmh) { int nCtrlID = ::GetDlgCtrlID(hWnd); WPARAM wParam = (WPARAM)nCtrlID; LPARAM lParam = (LPARAM)pnmh; return SendMessageToOwner(hWnd, WM_NOTIFY, wParam, lParam); } LRESULT ITCLIB::SendNotifyToOwner(CWnd* pControl, WORD wNotifyCode) { ASSERT(pControl != NULL); if (!pControl) { TRACE("The control pointer is invalid\n"); return -1; } // Delegate return SendNotifyToOwner(pControl->m_hWnd, wNotifyCode); } LRESULT ITCLIB::SendNotifyToOwner(CWnd* pControl, LPNMHDR pnmh) { ASSERT(pControl != NULL); if (!pControl) { TRACE("The control pointer is invalid\n"); return -1; } // Delegate return SendNotifyToOwner(pControl->m_hWnd, pnmh); } // @func Outputs a field and its associated data to a dump context. // // @syntax void DumpField(CDumpContext& dc, LPCTSTR lpszField, BOOL bValue); // @syntax void DumpField(CDumpContext& dc, LPCTSTR lpszField, CString strValue); // // @parm CDumpContext& | dc | A to output to. // @parm LPCTSTR | lpszField | The name of the field. // @parm BOOL | bValue | The field boolean value. // @parm CString | strValue | The field string value. // // @comm This function is in the ITCLIB namespace. void ITCLIB::DumpField(CDumpContext& dc, LPCTSTR lpszField, CString strValue) { const int MAX_LEN = 60; PrettyString(strValue, MAX_LEN); // Output the field name dc << lpszField; if (strValue.IsEmpty()) { dc << _T(" \r\n"); return; } if (strValue.GetLength() <= MAX_LEN) { dc << strValue << _T("\r\n"); return; } int nChar = 0; TCHAR sz[2] = _T(" "); BOOL bNeedNewline = FALSE; const CString strLead = _T("\t"); const CString strEndline = _T("\r\n"); // Output the first line for (; nChar < strValue.GetLength(); nChar++) { if (strValue[nChar] != _T('\n')) { sz[0] = strValue[nChar]; dc << sz; bNeedNewline = TRUE; } else { dc << strEndline; bNeedNewline = FALSE; break; } } if (bNeedNewline) dc << strEndline; bNeedNewline = FALSE; // The rest of the lines are indented while (nChar < strValue.GetLength()) { dc << strLead; for (nChar++; nChar < strValue.GetLength(); nChar++) { if (strValue[nChar] != _T('\n')) { sz[0] = strValue[nChar]; dc << sz; bNeedNewline = TRUE; } else { dc << strEndline; bNeedNewline = FALSE; break; } } if (bNeedNewline) dc << strEndline; bNeedNewline = FALSE; } } void ITCLIB::DumpField(CDumpContext& dc, LPCTSTR lpszField, BOOL bValue) { DumpField(dc, lpszField, (bValue) ? "Yes" : "No"); } // @func Work in progress. // // @comm This function is in the ITCLIB namespace. CString ITCLIB::AppProfileFindPath(CWinApp* pApp, LPCTSTR lpszSection, LPCTSTR lpszBasePathEntry, LPCTSTR lpszFileEntry, LPCTSTR lpszBaseDefault, LPCTSTR lpszFileDefault) { ASSERT(pApp != NULL); ASSERT(lpszSection != NULL); ASSERT(lpszFileEntry != NULL); CString strFile; CString strFullPath; CString strBasePath; strFile = pApp->GetProfileString(lpszSection, lpszFileEntry, lpszFileDefault); if (lpszBasePathEntry != NULL) strBasePath = pApp->GetProfileString(lpszSection, lpszBasePathEntry, lpszBaseDefault); if (!strFile.IsEmpty()) { if (!strBasePath.IsEmpty()) strFile = strBasePath + strFile; OFSTRUCT ofn; memset(&ofn, 0, sizeof(ofn)); if (::OpenFile(strFile, &ofn, OF_EXIST) != HFILE_ERROR) strFullPath = ofn.szPathName; } if (strFullPath.IsEmpty()) { CString strError; // TODO_LATER: Make these strings resources if (strFile.IsEmpty()) { strError.Format( "The following application profile setting is missing a file specification:\n" "\n" "Section:\t%s\n" "Entry:\t%s\n", "\n" "Please check the registry or the profile file.", lpszSection, lpszFileEntry); } else { strError.Format( "The following file cannot be found:\n" "%hs\n" "\n" "Please check the application profile setting '%s' in the '%s' section " "and make sure it contains a valid path.", (LPCTSTR)strFile, lpszFileEntry, lpszSection); } AfxMessageBox(strError); AfxThrowUserException(); } return strFullPath; } // @func Inserts a string into the specified string. // // @parm The index of the insertion. // @parm The string to insert into the destination. // @parm The string to insert into. // @parm The size of the buffer. // // @rdesc A pointer to
. // // @comm This function is in the ITCLIB namespace. LPCTSTR ITCLIB::InsertString(int nIndex, LPCTSTR lpszInsert, LPTSTR lpszDest, size_t nDestLen) { UNUSED(nDestLen); ASSERT((size_t)lstrlen(lpszInsert)+(size_t)lstrlen(lpszDest) < nDestLen); memmove(lpszDest+nIndex+lstrlen(lpszInsert), lpszDest, lstrlen(lpszDest)); strncpy(lpszDest+nIndex, lpszInsert, strlen(lpszInsert)); return lpszDest; } // @func This function trims leading and trailing whitespace from the // specified string. // // @syntax LPCTSTR TrimString(CString& rString); // @syntax LPCTSTR TrimString(LPTSTR lpszSrc); // // @parm CString& | rString | A reference to a
. // @parm LPTSTR | lpszSrc | A null-terminated string. // // @rdesc A pointer the the string. // // @comm This function is in the ITCLIB namespace. LPCTSTR ITCLIB::TrimString(CString& rString) { rString.TrimLeft(); rString.TrimRight(); return rString; } LPCTSTR ITCLIB::TrimString(LPTSTR lpszSrc) { TrimLeft(lpszSrc); TrimRight(lpszSrc); return lpszSrc; } // @func This function compares the rightmost characters in // the string with . // // @parm A null-terminated string. // @parm The string to compare to. // // @rdesc The results of
or -1 if has more // characters than
. // // @comm This function is in the ITCLIB namespace. int ITCLIB::CompareRight(LPCTSTR lpszSrc, LPCTSTR pszTail) { int n = lstrlen(lpszSrc) - lstrlen(pszTail); if (n < 0) return -1; return stricmp(lpszSrc+n, pszTail); } // @func This function removes the newline characters \r and \n // from the specified string. // // @syntax LPCTSTR StripNewline(CString& rString); // @syntax LPCTSTR StripNewline(LPTSTR lpszSrc); // // @parm CString& | rString | A reference to a
. // @parm LPTSTR | lpszSrc | A null-terminated string. // // @rdesc A pointer the the string. // // @comm This function is in the ITCLIB namespace. LPCTSTR ITCLIB::StripNewline(LPTSTR lpszSrc) { while ((lstrlen(lpszSrc) > 0) && ((lpszSrc[lstrlen(lpszSrc)-1] == '\r') || (lpszSrc[lstrlen(lpszSrc)-1] == '\n'))) { lpszSrc[lstrlen(lpszSrc)-1] = '\0'; } return lpszSrc; } LPCTSTR ITCLIB::StripNewline(CString& str) { StripNewline(str.GetBuffer(0)); str.ReleaseBuffer(); return str; } // @func This function splits a string into an array of substrings. // // @parm The string to split. // @parm The string that separates each substring. // @parm A reference to a to add the substrings to. // // @rdesc The number of strings in the array. // // @comm This function is in the ITCLIB namespace. // // @xref int ITCLIB::StringToStringArray(CString strText, CString strSeperator, CStringArray& array) { // Start with an empty array array.RemoveAll(); ASSERT(array.GetSize() == 0); // This is the beginning of the separator int nSep = strText.Find(strSeperator); int nSepLen = strSeperator.GetLength(); while (nSep != -1) { CString strLine = strText.Left(nSep); array.Add(strLine); // The next search starts after the separator strText = strText.Mid(nSep + nSepLen); nSep = strText.Find(strSeperator); } if (!strText.IsEmpty()) { array.Add(strText); } return array.GetSize(); } // @func This function concatenates the substrings in the specified // to form a single string. // // @parm A reference to a containing substrings. // @parm The separator to insert between each substring. // @parm A reference to a to fill. // // @rdesc The string . // // @comm This function is in the ITCLIB namespace. // // @xref
CString& ITCLIB::StringArrayToString(CStringArray& src, CString strSeperator, CString& strText) { strText.Empty(); // Create a local copy that we can manipulate CStringArray array; array.Copy(src); ASSERT(array.GetSize() == src.GetSize()); // Starting from the end, remove any empty strings // so we don't end up with a text buffer full of // separators. int ub = array.GetUpperBound(); while (ub >= 0) { CString strLine = array.GetAt(ub); if (strLine.IsEmpty()) { array.RemoveAt(ub); ub = array.GetUpperBound(); } else { ub = -1; // Exit the loop } } // Build the text buffer for (int i=0; i < array.GetSize(); i++) { // Each line should be seperated if ((i > 0) && !strSeperator.IsEmpty()) strText += strSeperator; strText += array.GetAt(i); } return strText; } // @func Converts a number representing bytes into a string description. // // @parm The number of bytes. // // @rdesc The string description. // // @comm This function is in the ITCLIB namespace. // // @ex | // ASSERT(BytesToString(10) == "10"); // ASSERT(BytesToString(1024) == "1KB"); // ASSERT(BytesToString(1024*1024) == "1.0MB"); // ASSERT(BytesToString(1024*1024*1024) == "1.00GB"); CString ITCLIB::BytesToString(long bytes) { CString str; const double OneKb = 1024; const double OneMb = OneKb * OneKb; const double OneGb = OneMb * OneKb; if (bytes < OneKb) { str.Format("%d", bytes); } else if ((bytes >= OneKb) && (bytes < OneMb)) { double kbytes = (double)bytes / OneKb; str.Format("%.0fKB", kbytes); } else if ((bytes >= OneMb) && (bytes < OneGb)) { double mbytes = (double)bytes / OneMb; str.Format("%.1fMB", mbytes); } else { ASSERT(bytes >= OneGb); double gbytes = (double)bytes / OneGb; str.Format("%.2fGB", gbytes); } return str; } // @func This function converts a value into a string using // . // // @parm The value to convert. // // @rdesc The string representation of the value. // // @comm This function is in the ITCLIB namespace. CString ITCLIB::ToString(long value) { CString str; str.Format("%ld", value); return str; } // @func Returns a object containing the HORZRES and VERTRES // of the specified device context in device coordinates. // // @parm A pointer to a device context. // // @rdesc The device resolution in device coordinates. // // @comm This function is in the ITCLIB namespace. // // @xref CSize ITCLIB::DeviceResolutionDP(CDC* pDC) { ASSERT_VALID(pDC); return CSize(pDC->GetDeviceCaps(HORZRES), pDC->GetDeviceCaps(VERTRES)); } // @func Returns a object containing the HORZRES and VERTRES // of the specified device context in logical coordinates. // // @parm A pointer to a device context. // // @rdesc The device resolution in logical coordinates. // // @comm This function is in the ITCLIB namespace. // // @xref CSize ITCLIB::DeviceResolutionLP(CDC* pDC) { CSize size = DeviceResolutionDP(pDC); pDC->DPtoLP(&size); return size; } // @func Sets the viewport origin of the specified device context. // // @parm A pointer to a device context. // @parm The origin in logical coordinates. // // @rdesc The previous origin in logical coordinates. // // @comm This function is in the ITCLIB namespace. CPoint ITCLIB::SetViewportOrgLP(CDC* pDC, CPoint origin) { ASSERT_VALID(pDC); // SetViewportOrg expects a POINT that is // in device units. This function deals with // logical units. pDC->LPtoDP(&origin); origin = pDC->SetViewportOrg(origin.x, origin.y); pDC->DPtoLP(&origin); return origin; } // @func This function uses to determine the // computer name of the current system. // // @rdesc The computer name of the current system. // // @comm This function is in the ITCLIB namespace. // // @xref CString ITCLIB::GetComputerName() { CString strComputer; DWORD dwLength = MAX_COMPUTERNAME_LENGTH + 1; // Have GetComputerName fill dwLength ::GetComputerName(strComputer.GetBufferSetLength(dwLength), &dwLength); strComputer.ReleaseBuffer(); // Now use a buffer length of dwLength dwLength++; // I don't trust the API ::GetComputerName(strComputer.GetBufferSetLength(dwLength), &dwLength); strComputer.ReleaseBuffer(); return strComputer; } // @func This function uses to determine the // user name of the current thread. // // @rdesc The user name of the current thread. // // @comm This function is in the ITCLIB namespace. // // @xref CString ITCLIB::GetUserName() { CString strUser; DWORD dwLength = 2; // Have GetUserName fill dwLength ::GetUserName(strUser.GetBufferSetLength(dwLength), &dwLength); strUser.ReleaseBuffer(); // Now use a buffer length of dwLength dwLength++; // I don't trust the API ::GetUserName(strUser.GetBufferSetLength(dwLength), &dwLength); strUser.ReleaseBuffer(); return strUser; } // @func This function splits a complete path into its folder and // file name components. The components can be separated by '\' or '/'. // // @parm A containing the full path of a file. // @parm A reference to a to be set to the folder portion // of the file's path. The folder will not contain a trailing backslash. // @parm A reference to a to be set to the file name. // // @comm This function is in the ITCLIB namespace. void ITCLIB::SplitPath(CString strFilePath, CString& strFolder, CString& strFileName) { int n = strFilePath.ReverseFind('\\'); if (n < 0) n = strFilePath.ReverseFind('/'); if (n >= 0) { strFolder = strFilePath.Left(n); strFileName = strFilePath.Right(strFilePath.GetLength()-n-1); } else { strFolder.Empty(); strFileName = strFilePath; } } // @func This function has the same functionality as the MFC // macro. The difference is that this function // will ASSERT if the object is NULL or is not of the specified type. // // @parm The runtime class of a class. // @parm A pointer to a . // // @rdesc The same thing does. // // @xref CObject* ITCLIB::TypeCastKindOf(CRuntimeClass* pClass, CObject* pObject) { ASSERT(pObject != NULL); ASSERT(pObject->IsKindOf(pClass)); // Do what DYNAMIC_DOWNCAST does if (pObject != NULL && pObject->IsKindOf(pClass)) return pObject; else return NULL; } const CObject* ITCLIB::TypeCastKindOf(CRuntimeClass* pClass, const CObject* pObject) { return (CObject*)ITCLIB::TypeCastKindOf(pClass, (const CObject*)pObject); } // @func This function does the same thing that does except // it always null terminates the string. // // @parm The destination buffer. // @parm The source string. // @parm The size of the destination buffer. // // @rdesc The destination buffer . // // @comm This function is in the ITCLIB namespace. LPCTSTR ITCLIB::CopyString(LPTSTR lpszDest, LPCTSTR lpszSrc, size_t nDestLen) { lpszDest[nDestLen-1] = '\0'; // strncpy doesn't guarentee this return strncpy(lpszDest, lpszSrc, nDestLen-1); } // @func This function is called when a pointer to a
object // is destroyed by one of the MFC template classes. This function deletes // the pointer. // // @parm A pointer to the * to delete. // @parm The number of elements to be destroyed. void AFXAPI DestructElements(CStringArray** pElements, int nCount) { ASSERT(nCount == 0 || AfxIsValidAddress(pElements, nCount * sizeof(CStringArray*))); // The default DestructElements just calls the destructor. // We want our list to free the memory too. for (; nCount--; pElements++) delete *pElements; } // @func This function is the same as the Win32 version of // it takes a parameter as the buffer value. // // @parm Pointer to a null-terminated string that specifies the environment variable. // @parm The to receive the value of the specified environment variable. // // @rdesc If the function succeeds, the return value is the number of characters // stored into the buffer , not including the terminating null // character. // // If the specified environment variable name was not found in the environment // block for the current process, the return value is zero. // // @comm This function is in the ITCLIB namespace. DWORD ITCLIB::GetEnvironmentVariable(LPCTSTR lpName, CString& strBuffer) { DWORD dwSize = ::GetEnvironmentVariable(lpName, NULL, 0); if (dwSize) { LPSTR lpszBuffer = strBuffer.GetBufferSetLength(dwSize); dwSize = ::GetEnvironmentVariable(lpName, lpszBuffer, dwSize); strBuffer.ReleaseBuffer(); } return dwSize; } // @mfunc Determines if the specified file exists. // // @parm The complete path to a file. // // @rdesc Nonzero if the file exists; otherwise 0. BOOL ITCLIB::FileExists(CString strFilePath) { CFileStatus fs; return CFile::GetStatus(strFilePath, fs); } // @mfunc Determines if the specified folder exists. // // @parm The complete path of a folder. // // @rdesc Nonzero if the file exists; otherwise 0. BOOL ITCLIB::FolderExists(CString strFolder) { CFileStatus fs; return CFile::GetStatus(strFolder, fs); } ////////////////////////////////////////////////////////////////////////////// // Inline function declarations expanded out-of-line #ifndef _ITC_ENABLE_INLINES static char _szInl[] = "ITAPI.inl"; #undef THIS_FILE #define THIS_FILE _szInl #define _ITC_INLINE #include "ITAPI.inl" #endif // _ITC_ENABLE_INLINES //////////////////////////////////////////////////////////////////////////////