Текстовые атрибуты (подчеркивание, сетка и c.) Не работают на моей собственной ручке - PullRequest
0 голосов
/ 14 апреля 2020

У меня проблема с атрибутами текста в моей программе на C ++. Проблема в том, что: если я установил 0x0F (белый) в качестве атрибута, программа работает, но если я установил 0x0F | COMMON_LVB_UNDERSCORE, программа установит только цвет. Я хочу создать библиотеку для консоли под названием CLib с использованием Windows API. Я думаю, проблема в том, что я использовал нестандартный дескриптор в качестве дескриптора консоли, поэтому я мог пропустить какой-либо атрибут доступа? Следующим является код создания дескриптора:

[Console.cpp]
Bool Console::create()
{
    if (!mConsole)
    {
        mConsole = CreateConsoleScreenBuffer(
            GENERIC_READ | GENERIC_WRITE,
            FILE_SHARE_READ | FILE_SHARE_WRITE,
            NULL,
            CONSOLE_TEXTMODE_BUFFER,
            NULL
        );
        return (Bool)mConsole;
    }
    return true;
}

Где typedef bool Bool; и

[Console.hpp]
class Console {
public:
    // code
private:
    // code
    static HANDLE mConsole;
}

, которые я определил в верхней части консоли. cpp файл как HANDLE Console::mConsole = NULL;. Самое интересное, что консоль окрашена программой, но другие атрибуты игнорируются. На данный момент я думаю, что настоящая проблема не в ручке, а в чем-то (как преобразование) в других файлах.

Я хочу спросить вас, действительно ли функция SetConsoleTextAttributes(HANDLE handle, DWORD attributes) устанавливает атрибуты только для стандартных дескрипторов? (если нет, я поделюсь всем кодом, чтобы понять проблему) Я говорю это, потому что если я напишу SetConsoleTextAttributes(GetStdHandle(STD_OUTPUT_HANDLE), same_attributes) работает!

Я буду sh, чтобы отправить весь код, но это очень долго ... файлов много ...

Ок, спасибо за советы. Я создаю 2 коротких файла, чтобы хорошо объяснить проблему;). Извините за переопределение Bool, но я придерживаюсь стиля Windows, чтобы переопределить все типы (эти файлы используют только 1 переопределение, это нормально?: P).

[Problem.hpp]
#pragma once

#include <Windows.h>
#include <iostream>

typedef std::wstring String;

struct RectInt
{
    COORD size;
    COORD position;
};

BOOL WINAPI ConsoleHandler(DWORD ctrltype);

COORD getCursorPosition(HANDLE handle);

class Console
{
public:

    Console(const String& title, const RectInt& rect)
    {
        this->create(rect);
        SetConsoleTitleW(title.c_str());
    }

    ~Console()
    {
        this->free();
        CloseHandle(mConsole);
    }

    ////////////////////////////////////////////////////////////////
    // the problem is when I call thisConsole function
    bool setAttributes(const DWORD& attributes)
    {
        mAttributes = attributes;
        return SetConsoleTextAttribute(mConsole, mAttributes);
    }
    bool setCursorPosition(const COORD& position)
    {
        return SetConsoleCursorPosition(mConsole, position);
    }
    bool setRect(const RectInt& rect)
    {
        mRect = rect;
        SMALL_RECT windowInfo =
        {
            mRect.position.X,
            mRect.position.Y,
            mRect.size.X,
            mRect.size.Y
        };
        return SetConsoleWindowInfo(mConsole, true, &windowInfo);
    }

    ////////////////////////////////////////////////////////////////

    bool allocate() { return AllocConsole(); }
    bool flush()
    {
        if (!SetConsoleActiveScreenBuffer(mConsole)) return false;
        return FlushConsoleInputBuffer(mConsole);
    }
    bool clear(const DWORD& attributes = 0x0F)
    {
        CONSOLE_SCREEN_BUFFER_INFO info;
        DWORD count;

        if (!GetConsoleScreenBufferInfo(mConsole, &info)) return false;
        if (!this->paint(attributes)) return false;

        if (!FillConsoleOutputCharacter(
            mConsole,
            L' ',
            info.dwSize.X * info.dwSize.Y,
            { 0,0 },
            &count
        )) return false;

        if (!FillConsoleOutputAttribute(
            mConsole,
            info.wAttributes,
            info.dwSize.X * info.dwSize.Y,
            { 0,0 },
            &count
        )) return false;

        if (!GetConsoleScreenBufferInfo(mConsole, &info)) return false;
        return this->setCursorPosition(mRect.position);
    }
    bool free() { return FreeConsole(); }

    ////////////////////////////////////////////////////////////////

    bool write(const String& text, const bool& flush = false)
    {
        if (!this->setCursorPosition(getCursorPosition(mConsole))) return false;
        DWORD charsWritten = 0;
        if (!WriteConsoleW(mConsole, text.c_str(), text.size(), &charsWritten, NULL)) return false;

        if (flush) return this->flush();
        return true;
    }

protected:

    bool create()
    {
        if (!mConsole)
        {
            mConsole = CreateConsoleScreenBuffer(
                GENERIC_READ | GENERIC_WRITE,
                FILE_SHARE_READ | FILE_SHARE_WRITE,
                NULL,
                CONSOLE_TEXTMODE_BUFFER,
                NULL
            );
            return (bool)mConsole;
        }
        return true;
    }
    bool create(const RectInt& rect)
    {
        if (!this->allocate())
        {
            FreeConsole();
            if (!this->allocate()) return false;
        }
        if (!this->create()) return false;

        if (!SetConsoleScreenBufferSize(
            mConsole,
            { rect.size.X, rect.size.Y }
        )) return false;

        if (!this->setRect(rect)) return false;
        if (!SetConsoleCtrlHandler(ConsoleHandler, true)) return false;

        if (!GetConsoleScreenBufferInfo(mConsole, &mBufferInfo)) return false;

        if (!SetConsoleActiveScreenBuffer(mConsole)) return false;

        if (!this->setAttributes(0x0F)) return false;
        return this->clear(mAttributes);
    }

private:

    static HANDLE mConsole;

    DWORD mAttributes;
    CONSOLE_SCREEN_BUFFER_INFO mBufferInfo;
    RectInt mRect;
};

и основной файл :

[Problem.cpp]
#include "Problem.hpp"
HANDLE Console::mConsole = nullptr;

BOOL WINAPI ConsoleHandler(DWORD ctrltype)
{
    return true;
}

COORD getCursorPosition(HANDLE handle)
{
    CONSOLE_SCREEN_BUFFER_INFO info;
    if (GetConsoleScreenBufferInfo(handle, &info)) return info.dwCursorPosition;
    return { 0,0 };
}

int main()
{
    ///////////////////////////////////////////////////////////
    ///                 Output (Standard)                   ///
    ///////////////////////////////////////////////////////////

    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0xF3 | COMMON_LVB_UNDERSCORE);

    std::cout << "Hello World!" << std::endl; //< print "Hello World!" on console with new attributes console attributes 
                                              // (0xF3 | COMMAND_LVB_UNDERSCORE)

    system("pause");

    ///////////////////////////////////////////////////////////
    ///         Output (using Console class)                ///
    ///////////////////////////////////////////////////////////

    // constructor passing title of console and rectangle (size,position)
    Console console(L"CLibTest", RectInt({ { 200,200 },{ 0,0 } }));

    console.setAttributes(0xF3 | COMMON_LVB_UNDERSCORE); //< do anything!!!! <- PROBLEM
    console.write(L"Hello World!\n", true); //< print "Hello World!" on console with default console attributes (0x0F)

    ///////////////////////////////////////////////////////////

    //std::cin.get(); //< to block automatically close ;)
    return 0;
}

Я надеюсь, что теперь это более завершено.

1 Ответ

0 голосов
/ 16 апреля 2020

Следующий код работает для меня. Можете попробовать?

CHAR data[] = "hello world\n";
DWORD writeBytes = 0;
HANDLE mConsole;

mConsole = CreateConsoleScreenBuffer(
    GENERIC_READ | GENERIC_WRITE,
    FILE_SHARE_READ | FILE_SHARE_WRITE,
    NULL,
    CONSOLE_TEXTMODE_BUFFER,
    NULL
);

SetConsoleActiveScreenBuffer(mConsole);

WriteConsoleA(mConsole, data, sizeof(data), &writeBytes, NULL);

DWORD mAttributes = 0x0F | COMMON_LVB_UNDERSCORE;
if (!SetConsoleTextAttribute(mConsole, mAttributes))
{
    MessageBox(NULL, TEXT("SetConsoleTextAttribute"),
        TEXT("Console Error"), MB_OK);
    return 1;
}

WriteConsoleA(mConsole, data, sizeof(data), &writeBytes, NULL);

Результат:

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...