⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wprintf.c

📁 <Win2k系统编程>源码.次数为国人自编,内容丰富,还是不错的.
💻 C
📖 第 1 页 / 共 3 页
字号:
    ...
    )
{
    va_list marker;
    INT i;

    va_start(marker, format);

    i = vwprintf(hwnd, format, marker);

    va_end(marker);

    return i;
}


/*****************************************************************************\
* vwprintf
*
* variable printf - works like the C runtime printf
*
* Arguments:
*    HWND hwnd - handle to the debug window
*    LPSTR format - pointer to the format string
*    va_list marker - pointer to marker
*
* Returns:
*    INT - number of arguments printed
\*****************************************************************************/
PUBLIC INT FAR cdecl
vwprintf(
HWND  hwnd,
LPSTR format,
va_list marker
)
{
    static HWND hwndLast = NULL;
    static CHAR  pchBuf[MAXBUFLEN];
    RECT  rect, rcClient;
    INT   iRet;
    INT   cLinesDisplayed;       // lines of output to show
    INT   cLinesFitInWindow;    // lines that can fit in the current window
    INT   cLinesNew;  // how much left to scroll
    PTXT  pTxt;
    HTXT  hTxt;
    BOOL  fNoScrollB;

    if (hwnd == NULL)
        hwnd = hwndLast;

    if (hwnd == NULL || !IsWindow(hwnd))
        return 0;  /* exit if bad window handle */

    hwndLast = hwnd;

    //
    // First format the line and wait until we can play with the Txt structure
    //
    iRet = wvsprintf((LPSTR)pchBuf, format, marker);
    hTxt = (HTXT)GetWindowLong(hwnd, 0);
    pTxt = (PTXT)LocalLock((HANDLE)hTxt);
    if(pTxt == NULL)
        return 0;  // exit if bad memory block

    EnterCrit(pTxt);

    //
    // Number of lines that we can display stuff in
    //
    cLinesFitInWindow   = LinesInDebugWindow(hwnd);

    if (cLinesFitInWindow > pTxt->iMaxLines) {
        fNoScrollB = TRUE;
        cLinesFitInWindow = pTxt->iMaxLines;
    } else {
        fNoScrollB = FALSE;
    }

    //
    // Number of lines actually displayed in the current window
    //
    cLinesDisplayed   = min(pTxt->iCount, cLinesFitInWindow);

    //
    // Return value is number of new lines to display
    //
    cLinesNew = InsertString(pTxt, pchBuf);

    //
    // Now make sure the new text is painted only if visable
    //
    GetClientRect(hwnd, (LPRECT) & rect);
    rcClient = rect;

    //
    // Calculate how much of the window to invalidate
    //
    rect.top += (cLinesDisplayed - 1) * pTxt->Tdy;

    InvalidateRect(hwnd, (LPRECT)&rect, TRUE);

    //
    // If we have more lines than we can display, scroll the window
    // such that the last line printed is now at the bottom
    //
    if (cLinesDisplayed + cLinesNew > cLinesFitInWindow) {
        cLinesNew = cLinesDisplayed + cLinesNew - cLinesFitInWindow;

        if (fNoScrollB) {
            rcClient.bottom = cLinesDisplayed * pTxt->Tdy;
            ScrollWindow(hwnd, 0, -cLinesNew * pTxt->Tdy, (LPRECT) &rcClient, (LPRECT) &rcClient);
        } else {
            wprintfSetScrollRange(hwnd, FALSE);
            DebugVScroll(hwnd, pTxt, cLinesNew);
        }
        LeaveCrit(pTxt);
    } else {
        LeaveCrit(pTxt);
    }

    LocalUnlock((HANDLE)hTxt);

    return(iRet);       /* return the count of arguments printed */
}

/*****************************************************************************\
* wprintfSetScrollRange
*
* Sets the scroll range of the debug window
*
* Arguments:
*    HWND hwnd - handle to the debug window
*    BOOL fRedraw - whether or not to redraw the window
*
* Returns:
*    VOID
\*****************************************************************************/

PRIVATE VOID
wprintfSetScrollRange (
HWND hwnd,
BOOL bRedraw
)
{
    PTXT pTxt;
    INT  iRange;
    INT  iLeftCritSect = 0;

    iSem++;
    pTxt = *(HTXT)GetWindowLong(hwnd, 0);

    /* Update the scroll bars */
    iRange = pTxt->iCount - 1 - LinesInDebugWindow(hwnd);

    if (iRange < 0) {
        iRange = 0;
        DebugVScroll(hwnd, pTxt, -pTxt->iTop);
    }

    while (GetCurrentThreadId() == (DWORD)pTxt->csSync.OwningThread){
	LeaveCrit(pTxt);
	iLeftCritSect++;
    }

    SetScrollRange(hwnd, SB_VERT, 0, iRange, FALSE);
    SetScrollPos(hwnd, SB_VERT, pTxt->iTop, bRedraw);

    if(iLeftCritSect) {
	EnterCrit(pTxt);
    }

    iRange = pTxt->MaxLen - CharsInDebugWindow(hwnd) + 1;
    if (iRange < 0) {
        iRange = 0;
        DebugHScroll(hwnd, pTxt, -pTxt->iLeft);
    }

    if(iLeftCritSect)
	LeaveCrit(pTxt);

    SetScrollRange(hwnd, SB_HORZ, 0, iRange, FALSE);
    SetScrollPos(hwnd, SB_HORZ, pTxt->iLeft, bRedraw);

    while (iLeftCritSect--) {
	EnterCrit(pTxt);
    }

    iSem--;
}

/*****************************************************************************\
* NewLine
*
* Calculates when a new line is needed in the debug window
*
* Arguments:
*    PTXT pTxt - pointer to the text
*
* Returns:
*    VOID
\*****************************************************************************/

PRIVATE VOID
NewLine (
PTXT pTxt
)
{
    INT iLast = LAST(pTxt);

    if (pTxt->iCount == pTxt->iMaxLines) {
        LocalFree ((HANDLE)pTxt->arLines[pTxt->iFirst].hText);
        pTxt->arLines[pTxt->iFirst].hText = NULL;
        INC (pTxt, pTxt->iFirst);
        if (pTxt->iTop > 0) {
            pTxt->iTop--;
        }
    } else {
        pTxt->iCount++;
    }
    iLast = LAST(pTxt);
    pTxt->arLines[iLast].hText = NULL;
    pTxt->arLines[iLast].iLen  = 0;
}

/*****************************************************************************\
* InsertString
*
* Inserts a string into the debug window
*
* Arguments:
*    PTXT pTxt - pointer to the text
*    CHAR *str - pointer to insertion string
*
* Returns:
*    INT - Line number at which string was inserted
\*****************************************************************************/

PRIVATE INT
InsertString (
PTXT  pTxt,
CHAR  *str
)
{
    CHAR   pchBuf[MAXBUFLEN];        /* intermediate buffer */
    INT    iBuf;
    INT    iLast = LAST(pTxt);
    INT    cLine = 0;

    for (iBuf = 0; iBuf < pTxt->arLines[iLast].iLen; iBuf++)
        pchBuf[iBuf] = (*pTxt->arLines[iLast].hText)[iBuf];

    while (*str != '\0') {
        while ((*str != '\n') && (*str != '\0'))
            pchBuf[iBuf++] = *str++;

        if (pTxt->arLines[iLast].hText != NULL)
            LocalFree((HANDLE)pTxt->arLines[iLast].hText);

        /* Test for the case of a zero length line, Only brian would do this */

        if (iBuf == 0)
            pTxt->arLines[iLast].hText == NULL;
        else {
            if ((pTxt->arLines[iLast].hText = (CHAR **)LocalAlloc(LHND, iBuf))
                == NULL) {
                return 0;
            }
        }

        pTxt->arLines[iLast].iLen = iBuf;
        while (--iBuf >= 0 )
            (*pTxt->arLines[iLast].hText)[iBuf] = pchBuf[iBuf];

        if (*str == '\n') {   /* Now do the next string after the \n */
            str++;
            cLine++;
            iBuf = 0;
            NewLine(pTxt);
            INC(pTxt, iLast);
        }
    }

    return cLine;
}

/*****************************************************************************\
* CopyToClipboard
*
* Copies all lines to the clipboard in text format.
*
* Arguments:
*   none
*
* Returns:
*   TRUE if successful, FALSE if not.
*
\*****************************************************************************/

BOOL
CopyToClipboard(
    VOID
    )
{
    PTXT pTxt;
    INT iQueue;
    INT cch;
    INT i;
    BOOL fSuccess = FALSE;
    LPSTR pBuf = NULL;
    LPSTR pb;

    pTxt = *(HTXT)GetWindowLong(ghwndPrintf, 0);

    EnterCrit(pTxt);

    iQueue = FIRST(pTxt);
    cch = 0;
    for (i = 0; i < pTxt->iCount; i++, INC(pTxt, iQueue))
    {
        if (pTxt->arLines[iQueue].hText != NULL)
        {
            //
            // Count the characters in the line, plus room for the
            // carriage return and newline.
            //
            cch += pTxt->arLines[iQueue].iLen;
            cch += 2;
        }
    }

    //
    // Add one for the terminating null.
    //
    cch++;

    if (!(pBuf = (LPSTR)GlobalAlloc(GMEM_DDESHARE, cch * sizeof(TCHAR))))
    {
        LeaveCrit(pTxt);
        return FALSE;
    }

    pb = pBuf;
    iQueue = FIRST(pTxt);
    for (i = 0; i < pTxt->iCount; i++, INC(pTxt, iQueue))
    {
        if (pTxt->arLines[iQueue].hText != NULL)
        {
            lstrcpy(pb, *pTxt->arLines[iQueue].hText);
            pb += pTxt->arLines[iQueue].iLen;
            *pb++ = '\r';
            *pb++ = '\n';
        }
    }

    LeaveCrit(pTxt);

    if (OpenClipboard(ghwndSpyApp))
    {
        EmptyClipboard();
        fSuccess = SetClipboardData(CF_TEXT, pBuf) ? TRUE : FALSE;
        CloseClipboard();
    }

    return fSuccess;
}

/*****************************************************************************\
* IsPrintfEmpty
*
* Used to determine if the printf window is empty or not.
*
* Arguments:
*   none
*
* Returns:
*   TRUE if the printf window is empty, FALSE if there is at least
*   one line in the window.
*
\*****************************************************************************/

BOOL
IsPrintfEmpty(
    VOID
    )
{
    PTXT pTxt;

    pTxt = *(HTXT)GetWindowLong(ghwndPrintf, 0);

    //
    // It is empty if the line count is zero (doesn't currently happen)
    // or if there is only one line and it is NULL.
    //
    return (pTxt->iCount == 0 ||
        (pTxt->iCount == 1 && pTxt->arLines[FIRST(pTxt)].hText == NULL))
        ? TRUE : FALSE;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -