所以,我偶然发现了Windows API的一个有趣的错误,我想知道是否有人对如何解决它有一些了解.似乎谷歌也在努力解决这个问题.应该注意的是,虽然我将在Qt源本身修复此问题,但问题在于Windows默认消息处理,而不是Qt.我将提到的所有文件都可以在线找到,因为它们都是开源库.下面是一个复杂的问题,我会尽量给出尽可能多的上下文.我花了很多时间和精力来解决这个问题,但由于我只是一名工程师大约8个月,我仍然缺乏经验,很可能错过了一些明显的东西.
上下文:
我编写了一个程序,使用Qt来自定义皮肤上的窗口.这些外观通过系统默认的非客户端UI外观.换句话说,我使用自定义绘制的框架(由Qt支持).从Qt5开始,当我的程序在任何Windows Aero之前的操作系统上运行时,我的程序出现了问题(低于XP且超过禁用Windows Aero的Vista).不幸的是,Qt开发人员已经确认他们不再真正支持XP,所以我不会依赖它们来修复bug.
错误:
在运行禁用了合成的计算机(禁用 Windows Aero或不存在)时,单击非客户区域中的任意位置将导致Windows在我的自定义外观上重新绘制其系统默认的非客户端UI.
我的研究
一些调试和调查让我进入了qwindowscontext.cpp中的qWindowsProc.我能够确定在窗口的皮肤被涂过之前要处理的最后一条窗口消息是WM_NCLBUTTONDOWN.这看起来很奇怪,所以我接受了互联网.
果然,我发现了一个名为hwnd_message_Handler.cc的文件来自Google的Chromium Embedded Framework(CEF).在该文件中有很多关于各种Windows消息的评论,由于一些疯狂的原因,导致重新定制系统默认的非客户端帧而不是自定义帧.以下是一个这样的评论.
// A scoping class that prevents a window from being able to redraw in response
// to invalidations that may occur within it for the lifetime of the object.
//
// Why would we want such a thing? Well, it turns out Windows has some
// "unorthodox" behavior when it comes to …
Run Code Online (Sandbox Code Playgroud) 如果您不熟悉 Gaffer on Games 文章“修复您的时间步长”,您可以在这里找到它:https : //gafferongames.com/post/fix_your_timestep/
我正在构建一个游戏引擎,为了让 std::chrono 更加舒适,我一直在尝试使用 std::chrono 实现一个固定的时间步长......几天了,但我不能似乎把我的头环绕在它周围。这是我正在努力的伪代码:
double t = 0.0;
double dt = 0.01;
double currentTime = hires_time_in_seconds();
double accumulator = 0.0;
State previous;
State current;
while ( !quit )
{
double newTime = time();
double frameTime = newTime - currentTime;
if ( frameTime > 0.25 )
frameTime = 0.25;
currentTime = newTime;
accumulator += frameTime;
while ( accumulator >= dt )
{
previousState = currentState;
integrate( currentState, t, dt );
t += …
Run Code Online (Sandbox Code Playgroud) 所以,我已经阅读了Boost.Siganl2的文档,我做了一些谷歌,我只是还没有找到我需要的东西.我所拥有的是控制器和视图概念.Controller将数据发送到View以进行渲染.我想要的是在我的控制器中调用Controller :: Update并在视图中触发OnUpdate函数.
这是我到目前为止尝试过的代码:
class Listener {
public:
virtual void OnUpdate() {};
};
class View :Listener
{
public:
View(void);
~View(void);
virtual void OnUpdate() override;
};
void View::OnUpdate()
{
std::cout << "Updating in View";
}
class Controller
{
public:
Controller(void);
~Controller(void);
void Update();
};
Controller::Controller(void)
{
// Signal with no arguments and a void return value
boost::signals2::signal<void ()> sig;
sig.connect(boost::bind(&Listener::OnUpdate, this, _1));
// Call all of the slots
sig();
system("pause");
}
Run Code Online (Sandbox Code Playgroud)
这不编译.我得到错误C2825:'F':当后跟'::'时必须是一个类或命名空间,但这只是因为我正在使用绑定错误.
有人知道如何使用带升压的信号/插槽来实现我想要的功能吗?
在为游戏生成树的上下文中考虑这段人为的代码:
// Pretend there's some code somewhere that associates the 0-100 number to its corresponding size.
enum class TreeSize : uint32_t
{
Small, // 0-9
Medium, // 10-60
Large,// 61-90
ExtraLarge, // 91-100
};
// returns tree size
int GenerateTree()
{
std::random_device rd;
std::mt19937_64 mt(rd());
std::uniform_int_distribution<int32_t> dist(0, 100);
return dist(s_mt);
}
Run Code Online (Sandbox Code Playgroud)
假设我想生成 1000 棵树,但绑定到特定的树大小比率。例如:
我该怎么做呢?有现成的东西可以实现这一点吗?这肯定是很多人以前必须面对的问题,是吗?
所以,我尝试过这个:
uint64_t size = 1 * 1000 * 1000 * 1000;
std::vector<char> data(size, 'a');
std::ofstream myfile;
myfile.open("test.dat");
for (auto it = data.begin(); it != data.end(); ++it)
{
myfile << *it;
}
myfile.close();
Run Code Online (Sandbox Code Playgroud)
它可以工作,但需要 15 分钟以上的时间才能发布。我运行的是 1TB NVME SSD 和 64GB RAM,我觉得我应该能够在几秒钟或不到一秒内完成此操作。
我确实可以访问 C++20。我更喜欢现代的东西,因为它具有可读性,只要它具有合理的性能。我觉得超过10秒就太慢了。
需要明确的是,将所有数据推回数组几乎是即时的。但写下来只需要几分钟的时间。
c++ ×5
bind ×1
boost ×1
c++-chrono ×1
c++11 ×1
file-io ×1
game-engine ×1
game-loop ×1
performance ×1
probability ×1
qt ×1
random ×1
signals ×1
winapi ×1
windows ×1