码迷,mamicode.com
首页 > 其他好文 > 详细

控制台程序添加滚轮滑动支持

时间:2015-04-17 00:57:31      阅读:162      评论:0      收藏:0      [点我收藏+]

标签:

控制台程序默认只能通过拖动滚动条来查看窗口中打印的内容,操作起来十分不方便。

本文通过多线程技术为控制台窗体添加鼠标滚轮滑动功能。值得注意的是,在有内容输出时,窗口会自动定位到输出的光标处;

这种情况最好是先暂停住主线程,然后再滚动鼠标查看打印的内容,查看完毕后,再继续执行主线程。

首先,需要让控制台程序的屏幕缓冲区高度 > 窗口高度(此时窗口右侧会产生滚动条),否则无需滚动窗口。

技术分享

下列代码实现了如下功能:

(1)滚动鼠标滑动窗口

(2)按空格键,暂停/继续主线程

#include <windows.h>

/**
* Scroll console window by relative coordinate
*/
static int ScrollByRelativeCoord(int iRows)
{
    CONSOLE_SCREEN_BUFFER_INFO csbiInfo; 
    SMALL_RECT srctWindow; 
    
    // Get the current screen buffer window position. 
    HANDLE hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE);
    
    if (! GetConsoleScreenBufferInfo(hConsoleOutput, &csbiInfo)) 
    { 
        return 0;
    }
    
    // Check whether the window is too close to the screen buffer top or bottom
    if (csbiInfo.srWindow.Top < iRows)
    {
        iRows = csbiInfo.srWindow.Top;
    }
    else if (csbiInfo.srWindow.Bottom > csbiInfo.dwSize.Y+iRows-1)
    {
        iRows = -1* (csbiInfo.dwSize.Y -1 - csbiInfo.srWindow.Bottom);
    }
    
    srctWindow.Top =- (SHORT)iRows;     // move top up
    srctWindow.Bottom =- (SHORT)iRows;  // move bottom up 
    srctWindow.Left = 0;         // no change 
    srctWindow.Right = 0;        // no change 
    
    if (! SetConsoleWindowInfo( 
        hConsoleOutput,          // screen buffer handle 
        FALSE,            // relative coordinates
        &srctWindow))     // specifies new location 
    {
        return 0;
    }
    return iRows;
}

DWORD WINAPI ConsoleInputEventProc(LPVOID lParam)
{
    // vc6 version sdk don‘t has OpenThread API, need get by call GetProcAddress;
    HANDLE hMainThreadHandle = NULL;
#if _MSC_VER <= 1200
    HMODULE hDll =::LoadLibrary("Kernel32.dll");
    if (hDll)
    {
        typedef HANDLE (__stdcall *OPENTHREAD) (DWORD, BOOL, DWORD);
        OPENTHREAD fnOpenThread = (OPENTHREAD)::GetProcAddress(hDll, "OpenThread");
        if (fnOpenThread)
        {
            hMainThreadHandle = fnOpenThread(THREAD_SUSPEND_RESUME, FALSE, (DWORD)lParam);
        }
    }
#else
    hMainThreadHandle = OpenThread(THREAD_SUSPEND_RESUME, FALSE, (DWORD)lParam);
#endif
    
    HANDLE hConsoleInput = GetStdHandle(STD_INPUT_HANDLE);
    
    BOOL bSuspend = FALSE;
    BOOL fContinue = TRUE;
    DWORD dwEvents;
    INPUT_RECORD input;
    while (fContinue &&
        ReadConsoleInput(hConsoleInput, &input, 1, &dwEvents) &&
        dwEvents > 0) 
    {
        switch (input.EventType) 
        {
        case KEY_EVENT:
            if (input.Event.KeyEvent.wVirtualKeyCode == VK_SPACE) 
            {
                if (input.Event.KeyEvent.bKeyDown && hMainThreadHandle != NULL)
                {
                    HANDLE hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE);
                    if (bSuspend)
                    {
                        SetConsoleTextAttribute(hConsoleOutput, FOREGROUND_GREEN);
                        printf("Resume MainThread\n");
                        ResumeThread(hMainThreadHandle);
                    }
                    else 
                    {
                        SetConsoleTextAttribute(hConsoleOutput, FOREGROUND_RED);
                        printf("Suspend MainThread\n");
                        SuspendThread(hMainThreadHandle);
                    }
                    
                    SetConsoleTextAttribute(hConsoleOutput, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
                    bSuspend = !bSuspend;
                }
            }
        case MOUSE_EVENT:
            if (input.Event.MouseEvent.dwEventFlags==4)// mousewheel
            {
                const int nLine = 5;
                if ((int)input.Event.MouseEvent.dwButtonState>0)// scroll up
                {
                    ScrollByRelativeCoord(nLine);
                }
                else// scroll up
                {
                    ScrollByRelativeCoord(-1*nLine);
                }
            }
            break;
        }
    }
    
    CloseHandle(hMainThreadHandle);
    return 0;
}

int main(int argc, char* argv[])
{    
    CreateThread(NULL, 0, ConsoleInputEventProc, (LPVOID)GetCurrentThreadId(), 0, NULL);

    int nLine = 60;
    while (nLine--)
    {
        printf("Hello World!\n");
        Sleep(1000);
    }

    Sleep(INFINITE);
    return 0;
}

 

控制台程序添加滚轮滑动支持

标签:

原文地址:http://www.cnblogs.com/kekec/p/4433649.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!