Forgotten Coder WIN32 nirvana

Pages: 12
Hi guys

I have reached nirvana. For this newbie at least is nirvana. I finish a small library in C++ for creating a screen and put some pixels in there. It's working. No win32 instructions in code. It's all wrapped. Two weeks banging with the head in the wall. BIG LOL.

So here is a taste of it with much room for improvement. Any suggestions ?


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

#include "turboscreen.hpp"

int main()
{

  ts::Screen s;
  ts::Pixel p;
  ts::Color c;
  ts::Event e;

  // Screen has a default screen of 800x600 located at 0,0 coords

  //draw the whole screen 800x600 in Yellow
  for (int y=0; y < 600; y++) {
    for (int x=0; x < 800; x++) {
      p.drawPixel(s.getScreenBuffer(),x,y,ts::Color::YELLOW);
    }
  }

  //draw a pixel in each corner of screen 800x600 default
  p.drawPixel(s.getScreenBuffer(),  0,  0,ts::Color::WHITE);
  p.drawPixel(s.getScreenBuffer(),799,599,ts::Color::WHITE);
  p.drawPixel(s.getScreenBuffer(),799,  0,ts::Color::WHITE);
  p.drawPixel(s.getScreenBuffer(),0  ,599,ts::Color::WHITE);

  s.renderScreen();

  //main loop
  while (s.getScreenId()!=nullptr) {
    e.waitEvent(s.getScreenId());
  }

  return 0;
}

Last edited on
if every function needs screenbuffer, you need a way to get it without passing it every time. Its likely a constant, but even so, that feels clunky.

I am a big hater on trying to make color objects. M$ made such a mess of it, I have been wary of them every since. I can't tell what you did there, but hopefully it is a using or typedef like thing for a char[4] or int32 or bitset or something like that. It just needs to be something very basic that you can assign in one operation yet get at it byte-wise.
Last edited on
Hi jonnin

Follow your advice in color system. I abandon SFML style for color declaration. Mine is better now. Who am i to talk about SFML Big Lol.

Added an RBGA function to Colour object. Alpha is not working. That's another beast for me.

I will be working in "hiding" s.getScreenBuffer() from drawPixel function. So many walls to hit. Big Lol.

Here is my last version of program.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

#include "turboscreen.hpp"

int main()
{
  using namespace ts;

  //ts::Screen s;
  //ts::Pixel p;
  //ts::Color c;
  //ts::Event e;

  Screen s;
  Pixel p;
  Color c;
  Event e;


  // Screen has a default screen of 800x600 located at 0,0 coords

  //draw the whole screen 800x600 in Yellow
  for (int y=0; y < 600; y++) {
    for (int x=0; x < 800; x++) {
      //ts::Pixel().drawPixel(s.getScreenBuffer(),x,y,ts::Color::RED);
      p.drawPixel(s.getScreenBuffer(),x,y,RED);
    }
  }

  //draw a pixel in each corner of screen 800x600 default

  /*
  p.drawPixel(s.getScreenBuffer(),  0,  0,ts::Color::WHITE);
  p.drawPixel(s.getScreenBuffer(),799,599,ts::Color::WHITE);
  p.drawPixel(s.getScreenBuffer(),799,  0,ts::Color::WHITE);
  p.drawPixel(s.getScreenBuffer(),0  ,599,ts::Color::WHITE);
  */

  p.drawPixel(s.getScreenBuffer(),  0,  0,c.RGBA(255,255,255)); //WHITE
  p.drawPixel(s.getScreenBuffer(),799,599,WHITE);
  p.drawPixel(s.getScreenBuffer(),799,  0,WHITE);
  p.drawPixel(s.getScreenBuffer(),0  ,599,WHITE);

  s.renderScreen();

  //main loop
  while (s.getScreenId()!=nullptr) {
    e.waitEvent(s.getScreenId());
  }

  return 0;
}
Last edited on
What's the difference between ts::Pixel and ts::Color?
Seems like ts::Pixel::drawPixel should be an operation on a Screen and not on a Pixel.
Last edited on
c.RGBA(255,255,255)); //WHITE

consider
c.RGB(255,255,255);
or
c.RGBA(255,255,255,0);
hi mbozzi

Pixel object is just that. The minimal thing that you can put on a screen. And for that you use drawPixel. Color object is not drawable on screen but you can use his functions in Pixel. Later if i add Rectangle object it will use Color too. But i can relate to your point of view. You wanted ts::screen::drawpixel :)
Hi jonnin

In my RGBA function you can ommit the alpha param or not. Alpha has a defaut of 255. Alpha isn't working. That's another beast that i will have to deal later.

My first version of "turboscreen", let's say 0.1 will have only the ability to create a screen and put pixels in it.
Hi guys

Added an openScreen function.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

#include "include/turboscreen.hpp"

int main()
{
  using namespace ts;

  Screen s; Pixel p; Color c; Event e;

  int x, y;

  s.openScreen(100,100,300,300);
  
  //draw the whole screen 800x600 in Yellow

  for (y=0; y < s.getHeight(); y++) {
    for (x=0; x < s.getWidth(); x++) {
      p.drawPixel(s.getScreenBuffer(),x,y,RED);
    }
  }

  //draw a little box on top left corner
  for (y=10; y < 30; y++) {
    for (x=10; x < 30; x++) {
      p.drawPixel(s.getScreenBuffer(),x,y,BLUE);
    }
  }

  //draw a pixel
  p.drawPixel(s.getScreenBuffer(),  15,  15,c.RGBA(255,255,255,0)); //WHITE

  s.renderScreen();

  //main loop
  while (s.getScreenOpen()) {  
    e.waitEvent(s.getScreenId());
  }

  return 0;
}


output screen: https://imgur.com/4FlsZ6m
Last edited on
Are you looking for a bit of code review on your library? Or just showing it off? Then you should post the contents of your custom header here so others can take a peek.

OR give a link to an online repository, such as github.

Nigh um-possible to play around with your library and critique it with ideas for possible improvement when only you have access to the header.

I created a custom header for making it easier to use the C++ random/time libraries so obtaining random numbers is about as easy as using the C library. Here's what I came up with:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
/* A simple toolkit to help beginners using <random> library an easier task */

// shamelessly stolen and adapted from a C++ working paper: WG21 N3551
// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3551.pdf

#ifndef __RANDOM_TOOLKIT__
#define __RANDOM_TOOLKIT__

#include <chrono>
#include <random>
#include <stdexcept>

namespace rtk
{
   static bool seeded { false };

   inline std::default_random_engine& urng()
   {
      static std::default_random_engine URNG { };

      return URNG;
   }

   inline void srand(bool FORCE_SEED = false)
   {
      static const std::seed_seq::result_type seeds[] { std::random_device {} (),
                                                        std::seed_seq::result_type(std::chrono::system_clock::now().time_since_epoch().count()) };
      static std::seed_seq sseq(std::begin(seeds), std::end(seeds));

      // the URNG can't be reseeded unless forced
      if (!seeded || FORCE_SEED)
      {
         urng().seed(sseq);

         seeded = true;
      }
   }

   inline void srand(signed seed, bool FORCE_SEED = false)
   {
      // the URNG can't be reseeded unless forced
      if (!seeded || FORCE_SEED)
      {
         urng().seed(static_cast<unsigned>(seed));

         seeded = true;
      }
   }

   // two function overloads to obtain uniform distribution ints and doubles
   inline int rand(int from, int to)
   {
      static std::uniform_int_distribution<> dist { };

      if (from > to) { throw std::invalid_argument("bad int params"); }

      return dist(urng(), decltype(dist)::param_type { from, to });
   }

   inline double rand(double from, double to)
   {
      static std::uniform_real_distribution<> dist { };

      if (from > to) { throw std::invalid_argument("bad double params"); }

      return dist(urng(), decltype(dist)::param_type { from, to });
   }

   // function for rolling dice, and checking if the # of pips is nonstandard
   inline int roll_die(int pips)
   {
      //check to see if the number of die pips is less than 2
      if (pips < 2)
      {
         return 0;
      }

      return rand(1, pips);
   }
}

#endif 

Now I don't have to deal with all the nitty-gritty details of using the C++ libraries when I want to generate random numbers for trivial purposes. Or use an experimental C++ library that isn't available with Visual Studio.

Here's a test engine for the header:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#include <array>
#include <iostream>
#include <numeric>
#include "random_toolkit.hpp"

int main()
{
   // "create" a random engine and randomize it
   rtk::srand();

   using card = unsigned;

   // manufacture a deck of cards:
   std::array<card, 52> deck;

   // create the cards, 0 (zero) to 51
   // setting warning level four causes std::iota heartburn from <numeric>
   std::iota(deck.begin(), deck.end(), 0);

   // lambdas to display the card in text representation:
   auto rank = [] (card c) { return "AKQJT98765432"[c % 13]; };
   auto suit = [] (card c) { return "SHDC"[c / 13]; };

   card count { };

   for (card c : deck)
   {
      std::cout << rank(c) << suit(c) << ' ';
      count++;

      if (0 == (count % 13)) { std::cout << '\n'; }
   }
   std::cout << '\n';

   // shuffle the deck:
   std::shuffle(deck.begin(), deck.end(), rtk::urng());

   count = 0;

   for (card c : deck)
   {
      std::cout << rank(c) << suit(c) << ' ';
      count++;

      if (0 == (count % 13)) { std::cout << '\n'; }
   }
   std::cout << '\n';

   for (unsigned loop { }; loop < 50; loop++)
   {
      std::cout << rtk::roll_die(6) << ' ';

      if ((loop + 1) % 20 == 0) { std::cout << '\n'; }
   }
   std::cout << "\n\n";

   // lambda to "flip a coin," returning a text representation of coin side
   auto flip_coin = [] () { return (rtk::rand(0, 1) ? "Heads" : "Tails"); };

   for (size_t loop { }; loop < 25; loop++)
   {
      std::cout << flip_coin() << '\t';

      if ((loop + 1) % 8 == 0) { std::cout << '\n'; }
   }
   std::cout << '\n';

   std::cout << "\nLet's see if we can have a non-standard die.....\nA die with 1 side: ";
   std::cout << rtk::roll_die(1) << '\n';

   std::cout << "A die with zero sides: ";
   std::cout << rtk::roll_die(0) << '\n';

   std::cout << "A die with negative sides: ";
   std::cout << rtk::roll_die(-6) << "\n\n";

   // let's try to create a bad distribution
   // setting warning level 4 causes VS to 'warn' about uninitialized variables
   std::cout << "Creating a bad random distribution, it should be be\n";
   std::cout << "encapsulated within a try/catch block.  Unless you want to crash.\n";

   try
   {
      int itest { rtk::rand(5, 2) };
   }

   catch (const std::exception& e)
   {
      std::cout << "\n>>> A standard exception was caught, with message '" << e.what() << "'\n";
   }

   try
   {
      double dtest { rtk::rand(5.3, 2.8) };
   }

   catch (const std::exception& e)
   {
      std::cout << "\n>>> A standard exception was caught, with message '" << e.what() << "'\n";
   }
}

If you follow the link I give in the header you might recognize where a largish portion of my test engine comes from.

Creating this simple header was a good learning experience, I enjoyed mashing it up.

Could the header be better, more "bullet proof," less "wordy?" Sure, but it works without having too many gaping holes in preventing serious runtime problems.

I have several other simple headers I can use and reuse when I need some functionality such as a simple menu or a "program pauser" when I don't want an app to close prematurely when it ends, and don't want to run the code within VS.
Last edited on
Hi Furry Guy

For now i am just showing it off. Later i will put my open source code in this site: http://www.turboscreen.org

I am working on ideas for an event system. Need more study. I only have a waitEvent function. :)


1
2
3
4
5
6
7
8
9
10
11
12
13
14

void Event::waitEvent(HWND hwnd)
{
   
    MSG message;

    if (PeekMessage(&message, hwnd, 0, 0, PM_REMOVE)) 
    {
      TranslateMessage(&message);
      DispatchMessage(&message);
    }  

}
Last edited on
Hint, hint, "just showing it off" means revealing the header as well. So far you have a lot of USELESS source code that no one can test or try.
Hi Furry Guy

My "turboscreen.hpp" won't tell you much. :)


1
2
3
4
5
6
7
8
9
10
11

#ifndef TURBOSCREEN_HPP
#define TURBOSCREEN_HPP

#include "Screen.hpp"
#include "Color.hpp"
#include "Pixel.hpp"
#include "Event.hpp"

#endif // TURBOSCREEN_HPP
So you continue to hide your implementation. Stop begging for accolades then.
Hi Ferry Guy

I am not doing this for accolades, glory or other kind of greetings. Much less competing with anyone. I am doing this for the fun for the jazz. Don't get it wrong but i will decide the timing for showing things. I won't beg for help either. People just give help or talk about this only if they want. I won't get mad either if people don't like my way of being. I am too old for that kind of sh.. Just an happy guy. :)
Last edited on
forgottencoder wrote:
I am not doing this for accolades, glory or other kind of greetings.
What do you want to get from posting it?
forgottencoder wrote:
People just give help or talk about this only if they want.
I think what Furry is trying to get across is that you are not giving much to allow people to have a discussion about it. We would be trying to second guess what you are doing, what you want to achieve, etc.
Grey, you understood implicitly what I was trying to elicit with all my hinting about, what is forgottencoder's reasons for posting woefully incomplete code and refusing polite requests for the missing code.

We certainly can't test it out and talk about how it works or doesn't work as the situation currently stands.

Shotgun comments about what little is exposed is an exercise in futility IMO. He could be going down the path of a really unsustainable model that will end up being a huge PITA and hassle the more he works on the code.

We can't really help and offer advice since we can't see how the magic works.

It isn't as if there are zero 3rd party libraries for doing graphical manipulation with Windows and C/C++ code.

I do understand wanting to learn by mashing code around when there is an itch to understand in desperate need of scratching. I have several standalone header libraries that were created for just that reason. They aren't by any stretch of imagination commercial production quality work, but they do what I want.

Grey, you certainly are more diplomatic about this than I am currently feeling. :)

Pax! *leaves the building*
Last edited on
Hi guys

You are both right but i still have no code to show yet. I moved this topic to the lounge. There i will hurt no feelings because i can talk about everything. The objective of this post is just to show my front coding of my raw library. Nothing more for now. Thanks for all comments so far.
*PLOINK!*
Hi guys

I added 2 functions to get current user screen resolution.

getHardwareScreenWidth() and getHardwareScreenHeight()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

#include "include/turboscreen.hpp"

int main()
{
  using namespace ts;

  Screen s; Pixel p; Color c; Event e; Keyboard k;

  int x, y;

  s.openScreen(0,0,s.getHardwareScreenWidth(),s.getHardwareScreenHeight());
  
  for (y=0; y < s.getHeight(); y++) {
    for (x=0; x < s.getWidth(); x++) {
      p.drawPixel(s.getScreenBuffer(),x,y,MAGENTA);
    }
  }

  for (y=10; y < 30; y++) {
    for (x=10; x < 30; x++) {
      p.drawPixel(s.getScreenBuffer(),x,y,BLUE);
    }
  }  

  s.renderScreen();

  //main loop
  while (!k.isKeyPressed(KEY_ESC)) {      
    e.waitEvent(s.getScreenId());
  }
  
  s.closeScreen();

  return 0;
}
Last edited on
What do they do if the system has more than one monitor?
Pages: 12