I want to draw text to a DirectX game, so I've injected a DLL which hooks EndPaint. My logic was that since EndPaint is supposed to be the last step in the WM_PAINT operation, I could, in my hook, draw the text, and then call EndPaint myself. By doing this, I avoid the DX interface altogether.
The problem is that it is doing absolutely nothing. Here is my code.
#include <windows.h>
#include "Hooks.h"
static const TCHAR g_cszMessage[] = TEXT("utterly fantastic");
BOOL (WINAPI * _EndPaint)(__in HWND hWnd, __in const LPPAINTSTRUCT lpPaint) = EndPaint;
BOOL WINAPI EndPaintHook(__in HWND hWnd, __in const LPPAINTSTRUCT lpPaint)
{
// write message
TextOut(lpPaint->hdc, 0, 0, g_cszMessage, lstrlen(g_cszMessage));
GdiFlush();
// return original
return _EndPaint(hWnd, lpPaint);
}
BOOL APIENTRY DllMain(__in HINSTANCE hModule, __in DWORD fdwReason, __in __reserved LPVOID lpvReserved)
{
UNREFERENCED_PARAMETER(lpvReserved);
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
if (AttachHook(reinterpret_cast<PVOID*>(&_EndPaint), EndPaintHook))
{
DisableThreadLibraryCalls(hModule);
break;
}
return FALSE;
case DLL_PROCESS_DETACH:
DetachHook(reinterpret_cast<PVOID*>(&_EndPaint), EndPaintHook);
break;
}
return TRUE;
}
I know the issue isn't with my AttachHook/DetachHook functions because I've tested via message boxes and confirmed that the hooks are installed. The text simply isn't showing up.
Anyone have any idea? I don't really want to hook the DX interface. Shouldn't it work either way, since WM_PAINT is still used at the base level?
Thanks in advance.
You are better off hooking the present of DirectX and then using ID3DXFont to do some font rendering. AFAIK WM_PAINT is not used for DirectX rendering.
Related
I'm making a digital whiteboard program with C++Builder.
It draws lines on a TImage using MouseDown and MouseMove events, like this:
Image1->Picture->Bitmap->Canvas->LineTo(x, y);
There is no problem when using the mouse.
However, when I use a Wacom tablet to draw the line, it doesn't fully recognize the movement of the pen. The problem occurs more when writing than when drawing a figure on the whiteboard.
I have no idea how to solve this problem.
What is the cause of the problem? How can I solve it?
Attached is the captured one to help you understand the problem. Same is written with mouse on the left side, and tablet pen on right side.
Code is like this:
void __fastcall TForm1::Image1MouseDown(TObject *Sender,
TMouseButton Button, TShiftState Shift, int X, int Y)
{
MouseClick = true;
Image1->Picture->Bitmap->Canvas->MoveTo(X,Y);
Image1->Picture->Bitmap->Canvas->LineTo(X,Y);
if (Pen==1){
if(type==0) //pen
{
Image1->Picture->Bitmap->Canvas->Pen->Color = ColorDialog1->Color;
PenColor = ColorDialog1->Color;
}
else if(type==1) //eraser
{
Image1->Picture->Bitmap->Canvas->Pen->Color = clWhite;
PenColor = clWhite;
}
Image1->Picture->Bitmap->Canvas->Pen->Width = ScrollBar1->Position;
PenWidth = ScrollBar1->Position;
}
}
//--------------------------------------------------------------------------
void __fastcall TForm1::Image1MouseMove(TObject *Sender,
TShiftState Shift, int X, int Y)
{
if(MouseClick)
{
Image1->Picture->Bitmap->Canvas->LineTo(X,Y);
}
}
#include "Simple_window.h"
#include "Graph.h"
#include <math.h>
#include <iostream>
#include <limits>
using namespace std;
int main(){
Simple_window win(Point(100,100),600,400,"Marks");
Graph_lib::Polygon poly;
bool over = true;
int n = 0;
while(over){
Marks pp("x");
pp.add(Point(300,200));
cout<<"Enter number of sides (3 or more): ";
while(!(cin>>n)){
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout<<"Enter number of sides (3 or more): ";
}
if(n<3){
break;
}
//Finding the angle and number of sides...
if(n%2 != 0){
//logic for polygon...
}
}else{
//logic for polygon...
}
}
poly.set_color(Color::magenta); // adjust properties of poly
win.attach (poly); // connect poly to the window
win.attach(pp);
win.wait_for_button(); // Display!
}
}
What does this program does it make n-sided polygons. After I set my polygon. I wish to reset it. After i enter the amount of sides in a polygon. I click on "next" it will ask me how many polygons again and repeat the process. Someone told me to call delete. However I'm not sure how I would type that in. As in delete poly.points? or delete polygon ? I tried a few but I kept getting errors.
My second question is on line 38. Originally I had it so If i entered a number less than 3 the program will end. But the program won't end. So i had to use break;
if(n<3){
over=false;
cout<<"why wont this end ?"<<endl;
}
boolean over is set to true. While true loop. If n < 3 over is false. thus end the program? it Wont end.
There is no need to reset the poly if you stick the declaration inside the first while loop.
while(over){
Graph_lib::Polygon poly;
...
win.wait_for_button();
}
Re: why your program won't end. Break is good enough but if you don't like using break
use continue
put the rest of the loop body in an else clause
Edit: Re: changing the title: I don't know the Simpe_Window interface: it is not part of FLTK - it is a Stroustrup creation. If it is derived from FL_Window, use label(new title).
I want to draw a line using mouse-event in Opencv in a webcam frame. I also want to erase it just like an eraser in MS-Paint.How can i do it? I dont have much idea about it. But i have this scrambled pseduo code from my head which can be completely wrong but i will write it down anyway. I would like to know how to implement it in c++.
So, i will have two three mouse event-
event 1- Mouse leftbuttonup-- this will be used to start the drawing
event 2- Mouse move -- this will be used to move the mouse to draw
event 3:- Mouse leftbuttondown-this will be used to stop the drawing.
event 4- Mouse double click - this event i can use to erase the drawing.
I will also have a drawfunction for a line such as line(Mat image,Point(startx,starty),Point(endx,endy),(0,0,255),1));
Now, i dont know how to implement this in a code format. I tried a lot but i get wrong results. I have a sincere request that please suggest me the code in Mat format not the Iplimage format. Thanks.
please find working code below with inlined explained comments using Mat ;)
Let me know in case of any problem.
PS: In main function, I have changed defauld cam id to 1 for my code, you should keep it suitable for you PC, probably 0. Good Luck.
#include <iostream>
#include <opencv\cv.h>
#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>
class WebCamPaint
{
public:
int cam_id;
std::string win_name;
cv::VideoCapture webCam;
cv::Size frame_size;
cv::Mat cam_frame, drawing_canvas;
cv::Point current_pointer, last_pointer;
cv::Scalar erase_color, paint_color;
int pointer_size;
//! Contructor to initialize basic members to defaults
WebCamPaint()
{
cam_id = 0;
pointer_size = 5;
win_name = std::string("CamView");
current_pointer = last_pointer = cv::Point(0, 0);
erase_color = cv::Scalar(0, 0, 0);
paint_color = cv::Scalar(250, 10, 10);
}
//! init function is required to set some members in case default members needed to change.
bool init()
{
//! Opening cam with specified cam id
webCam.open(cam_id);
//! Check if problem opening video
if (!webCam.isOpened())
{
return false;
}
//! Reading single frame and extracting properties
webCam >> cam_frame;
//! Check if problem reading video
if (cam_frame.empty())
{
return false;
}
frame_size = cam_frame.size();
drawing_canvas = cv::Mat(frame_size, CV_8UC3);
//! Creating Activity / Interface window
cv::namedWindow(win_name);
cv::imshow(win_name, cam_frame);
//! Resetting drawing canvas
drawing_canvas = erase_color;
//! initialization went successful ;)
return true;
}
//! This function deals wih all processing, drawing and displaying ie main UI to user
void startAcivity()
{
//! Keep doing until user presses "Esc" from Keyboard, wait for 20ms for user input
for (char user_input = cv::waitKey(20); user_input != 27; user_input = cv::waitKey(20))
{
webCam >> cam_frame; //Read a frame from webcam
cam_frame |= drawing_canvas; //Merge with actual drawing canvas or drawing pad, try different operation to merge incase you want different effect or solid effect
cv::imshow(win_name, cam_frame); //Display the image to user
//! Change size of pointer using keyboard + / -, don't they sound fun ;)
if (user_input == '+' && pointer_size < 25)
{
pointer_size++;
}
else if (user_input == '-' && pointer_size > 1)
{
pointer_size--;
}
}
}
//! Our function that should be registered in main to opencv Mouse Event Callback
static void onMouseCallback(int event, int x, int y, int flags, void* userdata)
{
/* NOTE: As it will be registered as mouse callback function, so this function will be called if anything happens with mouse
* event : mouse button event
* x, y : position of mouse-pointer relative to the window
* flags : current status of mouse button ie if left / right / middle button is down
* userdata: pointer o any data that can be supplied at time of setting callback,
* we are using here to tell this static function about the this / object pointer at which it should operate
*/
WebCamPaint *object = (WebCamPaint*)userdata;
object->last_pointer = object->current_pointer;
object->current_pointer = cv::Point(x, y);
//! Drawing a line on drawing canvas if left button is down
if (event == 1 || flags == 1)
{
cv::line(object->drawing_canvas, object->last_pointer, object->current_pointer, object->paint_color, object->pointer_size);
}
//! Drawing a line on drawing canvas if right button is down
if (event == 2 || flags == 2)
{
cv::line(object->drawing_canvas, object->last_pointer, object->current_pointer, object->erase_color, object->pointer_size);
}
}
};
int main(int argc, char *argv[])
{
WebCamPaint myCam;
myCam.cam_id = 1;
myCam.init();
cv::setMouseCallback(myCam.win_name, WebCamPaint::onMouseCallback, &myCam);
myCam.startAcivity();
return 0;
}
Because processing was slow by D3DPOOL_SCRATCH, I wrote the desktop capture program to reference for the report on the Internet. However, a result is a pitch-black picture. Is this the result of a console program or is there any other cause?
#include <stdio.h>
#include <Windows.h>
#include <d3d9.h>
void main()
{
CoInitialize(NULL);
LPDIRECT3D9 d3d9;
LPDIRECT3DDEVICE9 d3ddev;
d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
int ww = GetSystemMetrics(SM_CXSCREEN);
int wh = GetSystemMetrics(SM_CYSCREEN);
HWND hwnd = GetDesktopWindow();
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
d3dpp.BackBufferCount = 1;
d3dpp.BackBufferWidth = ww;
d3dpp.BackBufferHeight = wh;
d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
d3dpp.MultiSampleQuality = 0;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
d3dpp.hDeviceWindow = hwnd;
d3dpp.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
d3d9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &d3ddev);
IDirect3DSurface9* render;
IDirect3DSurface9* dest;
d3ddev->CreateOffscreenPlainSurface(ww, wh, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &dest, NULL);
d3ddev->GetRenderTarget(0, &render);
d3ddev->GetRenderTargetData(render, dest);
D3DLOCKED_RECT bits;
dest->LockRect(&bits, NULL, D3DLOCK_READONLY);
// If a capture is successful, colors other than black(0x00000000) should enter.
for(int i = 0; i < 100; i++){
printf("%02X ", *((BYTE*)bits.pBits + i));
}
dest->UnlockRect();
render->Release();
dest->Release();
d3ddev->Release();
d3d9->Release();
CoUninitialize();
}
This is nothing related to the application type, if you want to get the data of desktop image, you should use the following function
GetFrontBufferData
So instead of calling
d3ddev->GetRenderTarget(0, &render);
d3ddev->GetRenderTargetData(render, dest);
You should call
d3ddev->GetFrontBufferData(0, dest);
If you are running on a version of Windows before Windows 8, the GetFrontBufferData API works fine, as given by another answer. However, starting with Windows 8, there is a new desktop duplication API that can be used to capture the desktop in video memory, including mouse cursor changes and which parts of the screen actually changed or moved. This is far more performant than the D3D9 approach and is really well-suited to doing things like encoding the desktop to a video stream, since you never have to pull the texture out of GPU memory. The new API is available by enumerating DXGI outputs and calling DuplicateOutput on the screen you want to capture. Then you can enter a loop that waits for the screen to update and acquires each frame in turn.
If you want to encode the frames to a video, I'd recommend taking a look at Media Foundation rather than DirectShow, since Media Foundation has a lot better performance and can use D3D11 rather than D3D9 to do the encoding. It's also a bit easier to use, depending on your scenario. Take a look at Media Foundation's Sink Writer for the simplest method of encoding the video frames.
For full disclosure, I work on the team that owns the desktop duplication API at Microsoft, and I've personally written apps that capture the desktop (and video, games, etc.) to a video file at 60fps using this technique, as well as a lot of other scenarios.
I'm creating a custom component (derived from TCustomCategoryPanelGroup) and performing some custom draw operations. I want to handle when Themes are enabled and draw text appropriately.
Here is a snippet of some code I have in a draw function:
int theBaseDrawFlags = DT_EXPANDTABS | DT_SINGLELINE | DT_VCENTER | DT_LEFT;
theBaseDrawFlags = DrawTextBiDiModeFlags( theBaseDrawFlags );
if ( TCustomCategoryPanelGroup::hsThemed == PanelGroup->HeaderStyle && ThemeServices()->ThemesEnabled )
{
ThemeServices()->DrawText( ACanvas->Handle, ThemeServices()->GetElementDetails( tebNormalGroupHead ), m_CaptionTopLeft, m_TextRect, theBaseDrawFlags, 0 );
}
else
{
// Draw without themes
}
When I attempt to build this I receive the error:
Unresolved external __fastcall Themes::TThemeServices::DrawTextA(HDC__ *, Themes::TThemedElementDetails&, const System::WideString, Types::TRect&, unsigned int, unsigned int)' referenced from ....
As you can see it's looking for DrawTextA. I've looked at the Themes.hpp header and there is only a ThemeServices::DrawText function defined.
I'm not sure what's going on here. I thought perhaps that I was missing an import library, but all of the other ThemeServices functions that I use don't get link errors.
Anyone know what's going on here?
I guess you have #included some header (windows.h?) that contains something like this
#ifdef UNICODE
#define DrawText DrawTextW
#else
#define DrawText DrawTextA
#endif
You can probably put an #undef DrawText in your file to work around this. (See also Conflict with DrawText function.)