如何在不产生任何垃圾的情况下在 C 中获取像素
How to get pixel in C without generating any trash
我需要每秒至少检查屏幕上的四个像素五次。此外,这些像素不在应用程序上。如果可能的话,我想要一个不使用任何外部库的解决方案(换句话说,使用 graphics.h、windows.h 或 winusers.h)。如果解决方案使用 C++ 库也没关系。我尝试使用 GetPixel(),但它使用 audiodg.exe 生成了大量垃圾。如果您知道使用 SFML 或其他外部库的解决方案,也请在这里回答。
GetPixel()
的使用方法如下:
#include <Windows.h>
#include <iomanip>
#include <iostream>
void disp_colorref(COLORREF c) {
std::cout << std::setw(2) << static_cast<unsigned>(GetRValue(c))
<< std::setw(2) << static_cast<unsigned>(GetGValue(c))
<< std::setw(2) << static_cast<unsigned>(GetBValue(c));
}
int main()
{
HDC dt = GetDC(nullptr); // get screen DC
if (dt == nullptr) return 1; // error getting DC
COLORREF c = GetPixel(dt, 0, 0); // get the pixel color at 0, 0
if (c == CLR_INVALID) return 2; // error getting pixel
std::cout << std::hex;
disp_colorref(c); // display the pixel's RGB value
ReleaseDC(nullptr, dt); // release the DC
}
然而,如果 GetPixel
失败,上述内容将泄漏 DC
资源,因此您可以将资源放入 RAII 包装器中,这也消除了在您时手动调用 ReleaseDC
的需要完成了。示例:
#include <Windows.h>
#include <iomanip>
#include <iostream>
#include <utility>
// a RAII wrapper for a HDC
class dc_t {
public:
dc_t(HDC DC) :
dc(DC)
{
if (dc == nullptr) throw std::runtime_error("invalid DC");
}
dc_t(const dc_t&) = delete;
dc_t(dc_t&& rhs) noexcept :
dc(std::exchange(rhs.dc, nullptr))
{}
dc_t& operator=(const dc_t&) = delete;
dc_t& operator=(dc_t&& rhs) noexcept {
dc = std::exchange(rhs.dc, nullptr);
return *this;
}
~dc_t() {
if(dc) ReleaseDC(nullptr, dc);
}
operator HDC () { return dc; }
private:
HDC dc;
};
void disp_colorref(COLORREF c) {
std::cout << std::setw(2) << static_cast<unsigned>(GetRValue(c))
<< std::setw(2) << static_cast<unsigned>(GetGValue(c))
<< std::setw(2) << static_cast<unsigned>(GetBValue(c));
}
int main()
{
dc_t dt = GetDC(nullptr);
COLORREF c = GetPixel(dt, 0, 0);
if (c == CLR_INVALID) return 2;
std::cout << std::hex;
disp_colorref(c);
}
我需要每秒至少检查屏幕上的四个像素五次。此外,这些像素不在应用程序上。如果可能的话,我想要一个不使用任何外部库的解决方案(换句话说,使用 graphics.h、windows.h 或 winusers.h)。如果解决方案使用 C++ 库也没关系。我尝试使用 GetPixel(),但它使用 audiodg.exe 生成了大量垃圾。如果您知道使用 SFML 或其他外部库的解决方案,也请在这里回答。
GetPixel()
的使用方法如下:
#include <Windows.h>
#include <iomanip>
#include <iostream>
void disp_colorref(COLORREF c) {
std::cout << std::setw(2) << static_cast<unsigned>(GetRValue(c))
<< std::setw(2) << static_cast<unsigned>(GetGValue(c))
<< std::setw(2) << static_cast<unsigned>(GetBValue(c));
}
int main()
{
HDC dt = GetDC(nullptr); // get screen DC
if (dt == nullptr) return 1; // error getting DC
COLORREF c = GetPixel(dt, 0, 0); // get the pixel color at 0, 0
if (c == CLR_INVALID) return 2; // error getting pixel
std::cout << std::hex;
disp_colorref(c); // display the pixel's RGB value
ReleaseDC(nullptr, dt); // release the DC
}
然而,如果 GetPixel
失败,上述内容将泄漏 DC
资源,因此您可以将资源放入 RAII 包装器中,这也消除了在您时手动调用 ReleaseDC
的需要完成了。示例:
#include <Windows.h>
#include <iomanip>
#include <iostream>
#include <utility>
// a RAII wrapper for a HDC
class dc_t {
public:
dc_t(HDC DC) :
dc(DC)
{
if (dc == nullptr) throw std::runtime_error("invalid DC");
}
dc_t(const dc_t&) = delete;
dc_t(dc_t&& rhs) noexcept :
dc(std::exchange(rhs.dc, nullptr))
{}
dc_t& operator=(const dc_t&) = delete;
dc_t& operator=(dc_t&& rhs) noexcept {
dc = std::exchange(rhs.dc, nullptr);
return *this;
}
~dc_t() {
if(dc) ReleaseDC(nullptr, dc);
}
operator HDC () { return dc; }
private:
HDC dc;
};
void disp_colorref(COLORREF c) {
std::cout << std::setw(2) << static_cast<unsigned>(GetRValue(c))
<< std::setw(2) << static_cast<unsigned>(GetGValue(c))
<< std::setw(2) << static_cast<unsigned>(GetBValue(c));
}
int main()
{
dc_t dt = GetDC(nullptr);
COLORREF c = GetPixel(dt, 0, 0);
if (c == CLR_INVALID) return 2;
std::cout << std::hex;
disp_colorref(c);
}