MFC drawing board - c++

I made a heap on console. I've done all coding. Now I just need to show the heap tree on a drawing board. I am new to MFC and learned some basics like using a pDC pointer to draw nodes. Like pDC->ellipse(int x,int x2,int y,int y2). However I don't get how I will be able to show a complete tree on the board.
void CAst3View::OnDraw(CDC* pDC)
{
CAst3Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if(a.control_draw == true)
{
pDC->Ellipse(100, 100 ,500,500);
}
//if (a.height!=0)
//{
// pDC->Ellipse(100, 100 ,500,500);
//}
// TODO: add draw code for native data here
}
This gives me one circle on the drawing board.

The Ellipse function is used to draw a circle. To draw a complete tree, you may need to change the x- and y- coordinates and keep drawing the circle, then connect each circle using the LineTo function.
Related post which may help you: Tree Circle Draw Control

Related

Drawing bezier curve using four segments

I am trying to draw a bezier curve which uses 4 control points to draw a curve. However when I run my program, after 4 clicks with mouse I only see one pixel being drawn, am I missing something in my code? How can I get this to work properly?
void MyWindow::mousePressEvent(QMouseEvent *event)
{
if(event->button() == Qt::LeftButton)
{
x0 = event->x();
y0 = event->y();
point.setX(x0);
point.setY(y0);
std::vector<QPoint> myv;
myv.push_back(point);
counter+=1;
std::cout<<counter<<std::endl;
if(counter%4==0) {
drawBezier(myv[0], myv[1], myv[2], myv[3]);
}
}
update();
}
myv is local variable and you dont save its state to the new mousePressEvent
Get some "debug" info and see what you receive in drawBezier function.

MFC - How to draw pixel waves inside a rectangle

I am new to MFC trying to learn from the scratch.
I am trying to create a small dialog based application in VS2012 - MFC.
On the dialog window i have drawn a rectangle (in OnPaint event) like this.
CPaintDC dc(this);
CRect background1(10,10,208,92);
dc.Rectangle(10,10,208,92);
Then i filled the bacground with some color. Like this.
CBrush brush1;
brush1.CreateSolidBrush(RGB(2,3,4));
dc.FillRect(background1,&brush1);
Now i wanted to draw waves in form of pixels continuously inside the rectangle.
As of now what i have done is,
bool top = false;
for(i=10,j=92;i<200 && j>10;)
{
pDC->SetPixel(i,j,NewColor);
Sleep(10);
if(!top)
j-=1;
else
j+=1;
if(j%4==0)
{
i+=1;
}
if(j==12)
top=true;
if(j==90)
top = false;
}
I am just drawing the pixels straightaway on the window, but within the dimensions where the rectangle lies. And the waves stop as it reaches the right dimension of the rect. But i feel thats not the right way to do it.
I want to draw the waves inside the rectangle and also continuosly, like when it reacahes the right end it should move left and it should be continuous.
Is there any proper way in MFC to draw something inside a rectangle (technically inside another object)?
Please help me out.
The ScrollWindow function can be used to scroll the existing graph to the left. Then you draw the new data to the right of the scrolled area. The drawing will be much faster if you use the Polyline function instead of DrawPixel: Polyline draws an array of pixels.
I tried your code and just added some condition, so that if it reaches right side it should start moving toward left.
void CMyDlg::OnBnClickedOk()
{
CWnd *cWnd = FromHandle(m_hWnd);
CDC *pDC = cWnd->GetDC();
bool top = false;
bool right = false;
int i,j;
for(i=10,j=92;i<=200 && j>10;)
{
pDC->SetPixel(i,j,RGB(255,255,255));
Sleep(10);
if(!top)
j-=1;
else
j+=1;
if(j%4==0)
{
if(!right)
i++; // if reaches right side i--;
else{
i--;
}
}
if(j==12)
top=true;
else if(j==90)
top = false;
if(i == 200)// make right = true if reaches right side
right = true;
else if(i == 10)// make false it reaches left side
right = false;
}
}
I am getting output something like this
NOTE: this will cause infinite loop, you need to check condition where you have to stop printing pixels.
You are NOT looping with Sleep(10) in your WM_PAINT handler, are you?
MFC or not, you should separate your data processing from presentation.
It appears you are trying to do an animation; the simplest way to do it is to have an off-screen (memory) DC and drawing your pixels on it. At certain times (frame rate?), you would call parent's InvalidateRect()/UpdateWindow() pair. Then in ON_PAINT, you would BitBlt() your prepared DC onto your preferred location in the dialog.

Shuffling rendered primitives

This is just an experiment I'm doing, but suppose that we have three rectangles that are drawn:
void thisDialog::paintEvent(QPaintEvent *ev)
{
rectangle = new QRect(40, 80, 40, 90);
painter = new QPainter(this);
brush = new QBrush(QColor(QColor::green);
painter->fillRect(...);
painter->drawRect(...);
rectangle2 = new QRect(140, 80, 40, 90);
// and draw
rectangle3 = new QRect(240, 80, 40, 90);
// and draw...
}
And now I want to somehow shuffle the rectangles drawn. My solution is to use std::random_shuffle. The plan is we push all the rectangles into a vector thereof:
vector<QRect*> vecRect;
vecRect.push_back(rectangle);
// push back other rectangles
std::random_shuffle(vecRect.begin(), vecRect.end());
At this point, the order of the rectangles have been shuffled. The only problem is that although they're shuffled I have to somehow reflect that in their positions and also update what's shown on-screen for the changes to be apparent. So, I propose creating a function called shuffle. I want only the x-values to change, so the y-values and the spacings of the rectangles should be left alone.
void shuffle()
{
std::random_shuffle(vecRect.begin(), vecRect.end());
for (auto it : vecRect)
{
// do something to the x-values in rectangle; e.g.
it->setX(/*set something...*/);
}
}
To shuffle the rectangles along the x-axis and maintain the y-axis, and maintain the spacing in between I'd have to get a random number and add the spacing and ensure that it is within the window boundaries say 800x600.
Since I am new to Qt I have to know how Qt handles primitive positions, and so I guess that setX() from the docs would modify the x-position of the rectangle. My other enquiry is: how do we update the positions so they're reflected on what's drawn on-screen? Whenever I update positions it doesn't seem to take effect. I've tried update() but that doesn't seem to work.
Btw, I call the foresaid function through a key press, so if the key 'S' is pressed then the function is called.
TLDR; How can I shuffle x-positions in these rectangles and update their positions rendered?

Passing an SDL_Surface or clip_rect

I'm trying to write a bit of code in which I check to see if the mouse has been clicked on a certain SDL Surface. In the code example below, I have the SDL_Surface background which I am trying to check against the mouse position.
bool checkCollide(int myx, int myy, SDL_Surface* objectOne){
if(myx < objectOne->clip_rect.x) return false;
if(myx > objectOne->clip_rect.x + objectOne->clip_rect.w) return false;
if(myy < objectOne->clip_rect.y) return false;
if(myy > (objectOne->clip_rect.y + objectOne->clip_rect.h)) return false;
return true;
}
void main(){
SDL_Surface* background;
while(SDL_PollEvent(&event)){
if(event.type == SDL_MOUSEBUTTONDOWN){
if(checkCollide(event.button.x, event.button.y, background){
// run events
}
}
}
The problem I'm having is that when I try to run it as shown above, the code compiles fine but doesn't do anything. The collision check always fails. I have tried it in a lot of various combinations, including changing the parameters of checkCollide to SDL_Rect and passing the Surface's clip_rect property. The only completely successful way I've done it is to have a separate SDL_Rect with the same size and location as the SDL_Surface, and to check the collision against that. When I run it that way, it all works as I expect it to. Why isn't the surface (or clip_rect) passing correctly, or if it is, what am I doing wrong in the checkCollide function to cause it to fail?
The clip_rect property is not what you think it is:
From the SDL docs:
The clip_rect field is the clipping rectangle as set by
SDL_SetClipRect.
and SDL_SetClipRect
Sets the clipping rectangle for a surface. When this surface is the
destination of a blit, only the area within the clip rectangle will be
drawn into.
The rectangle pointed to by rect will be clipped to the edges of the
surface so that the clip rectangle for a surface can never fall
outside the edges of the surface.
If rect is NULL the clipping rectangle will be set to the full size of
the surface.
The problem is, that when you test the collision later on, the clip_rect x,y are always set to 0. The surface itself does not know about it's position on the screen.
A solution to this would be to create a Sprite like class that will have a Rect and a Surface.

Drawing Dice in a Windows C++ program?

We just started learning windows programming in C++. We have to make a program that has 4 die on the screen, and when the user presses 'SpaceBar', the die roll, or the number of dots on the die change randomly. Our professor hasent given us a lot of information, so I am kind of just looking for some direction.
Right now, I have 4 squares drawn on the screen, made with the Rectangle() function.
Rectangle(hDC,30,100,130,200);
Rectangle(hDC,180,100,280,200);
Rectangle(hDC,330,100,430,200);
Rectangle(hDC,480,100,580,200);
My question is 1) how would I go about drawing dots on these 'squares' and not on the 'screen'. So if I move the die upwards, the dots move with the square and dont just stay stationed painted on the screen. And 2.) How would I go about making those dots randomly change when spacebar is pressed (simulating that they have been rolled)?
Just looking for some direction, thanks.
1)
You will still have to draw them on the screen, but you can structure your program to realize the dots as part of the square.
void moveSquare()
{
//change square position
//change dots positions the same as you changed the square
}
2)
You can capture keypresses in your window with the WM_KEYDOWN and WM_KEYUP messages, or the WM_CHAR message. Just start a chain of changing how many dots are supposed to appear on the die when space is pressed (SetTimer could be handy), and let WM_PAINT do the work of painting the dots (or call something to calculate the positions of the dots, and let WM_PAINT loop through each dot it needs to draw.
void OnSpacePressed()
{
//start changing dots every so often, handled elsewhere
//maybe check if finished rolling before doing so
}
void calculateDotPositions()
{
switch (numberOfDots) {...} //hint: use the square as a reference point
}
void OnPaint()
{
//paint each sqaure
//paint each dot in the correct position, which should be updated with square
}
void OnChangeDots()
{
//change number of dots
//also start a new change to happen later if not done rolling
}
For drawing dots, use Warren P's reference link.
Another method is to create a bitmap or picture in memory. One for each of the 6 faces of the die. The objective here is to copy the bitmaps to the screen, rather than having to redraw them each time. Research "bitmap", and "bitblt".
You should make a routine that draws a die at the origin, offset by given coordinates. I'm not familiar with the particular library you are using, so I don't know what hDC is, but it should look something like the following.
void drawDie(HDC hDC, int xCoord, int yCoord, int dieValue)
{
Rectangle(hDC, -50 + xCoord, -50 + yCoord, 50 + xCoord, 50 + yCoord);
// draw some number of circles specified by dieValue at appropriate coordinates
// translated by xCoord and yCoord arguments
}
Then you can just redraw dice over your previous ones if you want them to change.