У меня проблема с атрибутами текста в моей программе на 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;
}
Я надеюсь, что теперь это более завершено.