📄 itapi.cpp
字号:
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//
// $NoKeywords: $
#include "stdafx.h"
#include "ITAPI.h"
#include <math.h>
using 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 <f AfxFindResourceHandle> to find the module
// of the specified resource. If the module is found, <f FindResource>
// is called to get a handle to the resource and <f LoadResource> is called
// to load the resource. Finally <f LockResource> is called to lock the
// resource in memory. If any of these functions fail, a <c CResourceException>
// 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 <f FindResource> 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 <f GetSystemMetrics>.
//
// @rdesc A <c CSize> 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 <f FormatMessage> to get a string
// description of the error codes returned by the <f GetLastError>
// function.
//
// @syntax CString GetLastErrorMessage();
// @syntax CString GetLastErrorMessage(DWORD dwLastError);
//
// @parm DWORD | dwLastError | An error code returned by <f GetLastError>.
//
// @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 <f GetLastError>.
//
// 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 <f WNetGetLastError> to determine the last
// network error code. This function will only return a valid result
// if <f GetLastError> 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 <f WNetGetLastError> to create a string
// description of the error codes returned by the <f GetLastWNetError>
// function.
//
// @syntax CString GetLastWNetErrorMessage();
// @syntax CString GetLastWNetErrorMessage(DWORD dwLastError);
//
// @parm DWORD | dwLastError | An error code returned by <f GetLastWNetError>.
//
// @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 <f GetLastWNetError>.
//
// 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 <f GetClientRect>, the top and left
// coordinates are always (0,0). This is useless when you need to call
// a function like the Win32 <f MoveWindow>. This function
// returns a rectangle with coordinates that can be passed to <f MoveWindow>.
//
// @parm HWND | hWnd | The window handle of the window.
// @parm CWnd* | pWnd | The <c CWnd> of the window.
// @parm CRect& | rc | A reference to a <c CRect> 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 <c CWnd> 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 <f PeekMessage>
// and if there are no <p nMsg> messages in the queue, one is posted
// using <f PostMessage>.
//
// @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 <p strAppend> to.
// @parm The prefix to add before <p strAppend> if <p str> is not empty.
// @parm The string to append. If this string is empty, <p str> is unaffected.
//
// @rdesc A reference to <p str>.
//
// @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 <p chSplit>
// 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 <c CString> that will contain the left half
// of the split.
// @parm A reference to a <c CString> 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 <c CString>.
//
// @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 <c CString>.
// @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 <c CString>.
//
// @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 <c CString>.
//
// @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 <c CString>.
// @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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -