Skip navigation

Monthly Archives: June 2009

Q: If two vectors form a plane in 3 space, then how come two vectors can be “skew” and never intersect?

A: Skew vectors that never intersect do not start both at the origin (of course, because if they did, the origin would be the intersection point and they would not be skew!)

Vectors that are skew never intersect – you have to present them in parametric form so that you’re sure the vector doesn’t start at the origin. An example is:

v1 = ( 1, 0, 0 ) + t( 0, 1, 0 ) ;
v2 = ( -1, 0, 0 ) + t( 0, 0, 1 ) ;

These are the two vectors on either side of the origin. One starts at ( 1, 0, 0 ), so right on the +x-axis, and goes STRAIGHT up.

The other vector starts on the -x-axis, at (-1,0,0) and goes STRAIGHT in the direction of +z.

Because one vector goes straight up and down, and the other vector goes back and forth in z, they’ll never hit each other. But the vectors AREN’T parallel.

WordPress doesn’t allow you to use just ANY tags. These are the tags you CAN use:

the indented part are the attributes those tags can use.

	$allowedposttags = array(
		'address' => array(),
		'a' => array(
			'class' => array (),
			'href' => array (),
			'id' => array (),
			'title' => array (),
			'rel' => array (),
			'rev' => array (),
			'name' => array (),
			'target' => array()),
		'abbr' => array(
			'class' => array (),
			'title' => array ()),
		'acronym' => array(
			'title' => array ()),
		'b' => array(),
		'big' => array(),
		'blockquote' => array(
			'id' => array (),
			'cite' => array (),
			'class' => array(),
			'lang' => array(),
			'xml:lang' => array()),
		'br' => array (
			'class' => array ()),
		'button' => array(
			'disabled' => array (),
			'name' => array (),
			'type' => array (),
			'value' => array ()),
		'caption' => array(
			'align' => array (),
			'class' => array ()),
		'cite' => array (
			'class' => array(),
			'dir' => array(),
			'lang' => array(),
			'title' => array ()),
		'code' => array (
			'style' => array()),
		'col' => array(
			'align' => array (),
			'char' => array (),
			'charoff' => array (),
			'span' => array (),
			'dir' => array(),
			'style' => array (),
			'valign' => array (),
			'width' => array ()),
		'del' => array(
			'datetime' => array ()),
		'dd' => array(),
		'div' => array(
			'align' => array (),
			'class' => array (),
			'dir' => array (),
			'lang' => array(),
			'style' => array (),
			'xml:lang' => array()),
		'dl' => array(),
		'dt' => array(),
		'em' => array(),
		'fieldset' => array(),
		'font' => array(
			'color' => array (),
			'face' => array (),
			'size' => array ()),
		'form' => array(
			'action' => array (),
			'accept' => array (),
			'accept-charset' => array (),
			'enctype' => array (),
			'method' => array (),
			'name' => array (),
			'target' => array ()),
		'h1' => array(
			'align' => array (),
			'class' => array ()),
		'h2' => array(
			'align' => array (),
			'class' => array ()),
		'h3' => array(
			'align' => array (),
			'class' => array ()),
		'h4' => array(
			'align' => array (),
			'class' => array ()),
		'h5' => array(
			'align' => array (),
			'class' => array ()),
		'h6' => array(
			'align' => array (),
			'class' => array ()),
		'hr' => array(
			'align' => array (),
			'class' => array (),
			'noshade' => array (),
			'size' => array (),
			'width' => array ()),
		'i' => array(),
		'img' => array(
			'alt' => array (),
			'align' => array (),
			'border' => array (),
			'class' => array (),
			'height' => array (),
			'hspace' => array (),
			'longdesc' => array (),
			'vspace' => array (),
			'src' => array (),
			'style' => array (),
			'width' => array ()),
		'ins' => array(
			'datetime' => array (),
			'cite' => array ()),
		'kbd' => array(),
		'label' => array(
			'for' => array ()),
		'legend' => array(
			'align' => array ()),
		'li' => array (
			'align' => array (),
			'class' => array ()),
		'p' => array(
			'class' => array (),
			'align' => array (),
			'dir' => array(),
			'lang' => array(),
			'style' => array (),
			'xml:lang' => array()),
		'pre' => array(
			'style' => array(),
			'width' => array ()),
		'q' => array(
			'cite' => array ()),
		's' => array(),
		'span' => array (
			'class' => array (),
			'dir' => array (),
			'align' => array (),
			'lang' => array (),
			'style' => array (),
			'title' => array (),
			'xml:lang' => array()),
		'strike' => array(),
		'strong' => array(),
		'sub' => array(),
		'sup' => array(),
		'table' => array(
			'align' => array (),
			'bgcolor' => array (),
			'border' => array (),
			'cellpadding' => array (),
			'cellspacing' => array (),
			'class' => array (),
			'dir' => array(),
			'id' => array(),
			'rules' => array (),
			'style' => array (),
			'summary' => array (),
			'width' => array ()),
		'tbody' => array(
			'align' => array (),
			'char' => array (),
			'charoff' => array (),
			'valign' => array ()),
		'td' => array(
			'abbr' => array (),
			'align' => array (),
			'axis' => array (),
			'bgcolor' => array (),
			'char' => array (),
			'charoff' => array (),
			'class' => array (),
			'colspan' => array (),
			'dir' => array(),
			'headers' => array (),
			'height' => array (),
			'nowrap' => array (),
			'rowspan' => array (),
			'scope' => array (),
			'style' => array (),
			'valign' => array (),
			'width' => array ()),
		'textarea' => array(
			'cols' => array (),
			'rows' => array (),
			'disabled' => array (),
			'name' => array (),
			'readonly' => array ()),
		'tfoot' => array(
			'align' => array (),
			'char' => array (),
			'class' => array (),
			'charoff' => array (),
			'valign' => array ()),
		'th' => array(
			'abbr' => array (),
			'align' => array (),
			'axis' => array (),
			'bgcolor' => array (),
			'char' => array (),
			'charoff' => array (),
			'class' => array (),
			'colspan' => array (),
			'headers' => array (),
			'height' => array (),
			'nowrap' => array (),
			'rowspan' => array (),
			'scope' => array (),
			'valign' => array (),
			'width' => array ()),
		'thead' => array(
			'align' => array (),
			'char' => array (),
			'charoff' => array (),
			'class' => array (),
			'valign' => array ()),
		'title' => array(),
		'tr' => array(
			'align' => array (),
			'bgcolor' => array (),
			'char' => array (),
			'charoff' => array (),
			'class' => array (),
			'style' => array (),
			'valign' => array ()),
		'tt' => array(),
		'u' => array(),
		'ul' => array (
			'class' => array (),
			'style' => array (),
			'type' => array ()),
		'ol' => array (
			'class' => array (),
			'start' => array (),
			'style' => array (),
			'type' => array ()),
		'var' => array ());

	/**
	 * Kses allowed HTML elements.
	 *
	 * @global array $allowedtags
	 * @since 1.0.0
	 */
	$allowedtags = array(
		'a' => array(
			'href' => array (),
			'title' => array ()),
		'abbr' => array(
			'title' => array ()),
		'acronym' => array(
			'title' => array ()),
		'b' => array(),
		'blockquote' => array(
			'cite' => array ()),
		//	'br' => array(),
		'cite' => array (),
		'code' => array(),
		'del' => array(
			'datetime' => array ()),
		//	'dd' => array(),
		//	'dl' => array(),
		//	'dt' => array(),
		'em' => array (), 'i' => array (),
		//	'ins' => array('datetime' => array(), 'cite' => array()),
		//	'li' => array(),
		//	'ol' => array(),
		//	'p' => array(),
		'q' => array(
			'cite' => array ()),
		'strike' => array(),
		'strong' => array(),
		//	'sub' => array(),
		//	'sup' => array(),
		//	'u' => array(),
		//	'ul' => array(),
	);

This is from kses.php, wordpress source code.

The dot product

1.

Another way to find the dot product is:

2.

Projections of a vector u onto a vector v are found in two ways I can see so far:

3.

Which is 100% equal to:

4.

WHERE is a unit vector pointing in the same direction as v.

SO we can also say:

5.

Where v has become a unit vector, totally.

Keep in mind the difference between equations 4 and 5 is in 4, v isn’t necessarily normalized when its used in the dot product operation, so you need to divided by |v| to “cancel its effect” on the final result. notice in all of these, we divide by v enough times so that the actual magnitude of v PLAYS NO ROLE in projvu, only the direction of v matters.

Finally you’ll see the following definition usually in physics books:

6.

Where t is the angle between vectors u and v.

This 6th formula follows if you study formula 3 and move things around a bit..

taking formula 3:

Notice that from formula 1, we have:

So, re-arranging formula 3 a bit now..

All I did there was add a |u| to the denominator, and separate the |v|2 into |v||v|

Ok?

Next, sub in

Then we get:

Now notice that , (v as a unit vector), so

where is a unit vector pointing in the direction of the vector v you are trying to project u onto.

Technical knowledge, ability to express ideas, assume leadership, inspire enthusiasm in people as “commodities”.

TRACK 1.
8:50: “This BOOK”

TRACK 2.
11:34.
criticism is futile, dangerous. incurs resentment.

humans thirst for approval, are scared of criticism

– hard hat guys. the dudes wouldn’t wear their hats. the foreman told them REGULATIONS SAY YOU MUST WEAR THE HATS. But this didn’t work well.

– then he tried to get them to change by first asking if the hats were uncomfortable, trying to sympathize with them – seeing why they weren’t wearing the hats. THEN he told them why they had to wear the hats — protection — more ppl wore the hats after that.

“Father Forgets” – W. Livingston Learned. A good piece of writing about a father who expected too much from his young son and constantly criticized him.

Principle 1. DOn’t criticize, condemn or complain.

TRACK 4.
Chapter 2. The big secret of dealing with people.

Freud’s 2 desires of men:
1. Desire to be great **
2. Sex urge.

Dewey: Desire to be important — Like Freud’s “desire to be great”

Humans have a CRAVING to be appreciated
– people who have this food will hold control

Humans have a “gnawing desire for attention”

– how people get their feeling of importance determines character…
– criminals from getting their picture in the paper as a great criminal at large
– good people from being recognized for good works

TRACK 5.
6:00 into

Charles Schwab:

– I consider my ability to arouse enthusiasm among my people the greatest asset that I possess. And the way to develop the best that is in a person is by appreciation and encouragement. There is nothing else that so kills the ambition of a person as criticism from superiors. I never criticize anyone. I believe in giving a person incentive to work. So I’m anxious to praise, but loathe to find fault. If I like anything, I am hearty in my approbation and lavish in my praise.

Average people do the exact opposite. complain if bad, if they do like something, they say nothing.

“Once I did bad
and that I heard ever
Twice I did good
but that I heard never”

– people do better work under spirit of approval. moreso then spirit of being derailed and derided.

#1 reason for runaway wives is lack of appreciation.

– flattery is counterfeit.

– flattery is telling other people what you think about yourself.

appreciation vs. flattery:
good bad

TRACK 6. Chapter 3.

He who can do this has the world with him. He who cannot walks a lonely way.

You don’t fish with strawberries (what you like), you use worms.

“bait the hook to suit the fish”.
– you are interested in what you want.
– others are interested in what they want

only way to influence people is to talk in terms of what others want, and show them how to get it.

“Influencing Human Behaviour”

“Arouse in the other person an eager want”

TRACK 7.

(right at the beginning)

Henry Ford

“If there is any one secret of success it lies in the ability to get the other person’s point of view and see things from that person’s angle as well as from your own.”

90% of ppl ignore it 90% of the time.

“people who can put themselves in the place of other people need never worry about what the future has in store for them.”

arousing an eager want for something in another person.

Track 8: Review:
Principle 1. DOn’t criticize, condemn or complain.
Principle 2. Give honest and sincere appreciation
Principle 3. Arouse in the other person an eager want.

Track 9: SIX WAYS TO MAKE PEOPLE LIKE YOU.

Dog as a natural friend. Behind his show of affection, there’s no alterior motive.

– dogs don’t have to work for a living — they make living by giving love

* You can make more friends in 2 months by becoming GENUINELY interested in other people than you can in 2 years by trying to get other people interested in YOU.

– Some people blunder through life trying to get others interested in themselves. This doesn’t work. People are not interested in you or me, people are interested in themselves.

– “I” is the most commonly used word in the English language.

– If we merely try to impress people and get people interested in us, then we will never have many true, sincere friends. Friends, real friends, are not made that way.

Alfred Adler: wrote a book:”What life should mean to you.”
“It is the individual who is not interested in his fellow men who has the greatest difficulties in life and provides the greatest injury to others. It is from among such individuals that ALL human failures spring..”

– If the author doesn’t like people, then people won’t like his writing

– you have to be interested in people to be a successful writer of stories.

– most of this track is about *Genuine interest in others*

12:30
One can win the attention and time and cooperation of even the most sought after people by becoming genuinely interested in them.

how he got some important people to guest lecture at his seminars:
“We admired their work and were deeply interested in getting their advice and learning the secrets of their success. We realize you’re too busy to prepare a lecture, so we enclosed a list of questions to answer about themselves and their methods of WORK.”

13:40 – people _like_ people who have admiration for them.

This dude _tactfully_ got everyone he knows’ birthdays and then sent birthday greetings to each of them.

Pabloious Sirus (100 BC):
– “We are interested in others WHEN they are interested in us”

PART 2 Principle 1: “Become genuinely interested in other people!!”

TRACK 10:

Talk of smiles.

Principle 2: Smile.

TRACK 11: If you don’t do this, you are heading for trouble.

Jim Farley: uncanny ability to remember people’s names.

– Remembering a name advantage
– forget/mispell, disadvantage.
This track was all about names and using names. The effectiveness of using names. Perhaps this was what made my students like me so much. I knew their names.

TRACK 12:
Principle 3: A person’s name is to that person, the sweetest and most important sound in any language.

TRACK 13: EASY WAY TO BECOME A GOOD CONVERSATIONALIST

– some people want an interested listener so she can expand her ego and tell about where she had been.

– interesting conversationalist — called this because listened intently.

– good listening is one of the highest compliments you can pay anyone.

– rapt attention

A good conversationalist as a good listener.

Successful business interviews: exclusive attention to the person speaking to you.

Listening as a form of activity.

Listening attentively shows you care about someone.

Sometimes people don’t want advice. They want an AUDIENCE.

Freud’s manner of listening was concentrated.. mild eyes, low voice, gestures few, but attention he gave, appreciation of what he said — no idea what its like to be listened to LIKE THAT.

– People despise people who NEVER LISTEN TO ANYBODY for long.

– To be a good conversationalist, be an attentive listener.

To be interesting, be INTERESTED.

Ask questions the other person will enjoy answering.

Encourage others to talk about themselves and their accomplishments

People you talk to are 100 times more interested in themselves and their problems than you and your problems.

PRINCIPLE 4: Be a good listener and encourage others to talk about themselves.

Track 14:
CHAPTER 5: How to interest people.
– Researching people’s backgrounds and studying it.. opening conversation based on these things

Anyone who was a guest of Theodore Roosevelt astonished by his range of knowledge

Roosevelt knew what to SAY to people.
– whenever he knew he would have a visitor, he would read up on the subject in which he knew his guest was particularly interested.
– royal road to person’s heart is to talk about things that he/she treasures most.

TRACK 15:

PRINCIPLE 5: Talk in terms of other people’s interests

guy who succeeded at getting past secretary and to bigwig guy to get job..

TRACK 16:

Chapter 6: How to make people like you instantly.
– the guy complemented someone on his head of hair.

LAW: Always make the other person feel important.

John Dewey: “The desire to be important is the deepest urge in human nature”

William James
“The deepest urge in human nature is the craving to be appreciated.”

-This is the urge that differentiates us from animals;
this is the urge that is really responsible for civilization itself;

Important precept:
– “Do unto others as you would have others do unto you”

All the time, everywhere.

6:40
“I’m sorry to trouble you”

Courtesy’s like this “oil the cogs of everyday life”

Rosette considered himself important.

PRINCIPLE 6: Make the other person feel important, and do it sincerely.

TRACK 17: Summary of 6 principles of this chapter.

TRACK 18:

Part 3: How to win people to your way of thinking.

Chapter 1. You can’t win an argument.

– You can measure the size of a person by what makes him or her angry!

PRINCIPLE 1: The only way to get the best of an argument is to avoid it

TRACK 19:
Chapter 2. A sure way of making enemies and how to avoid it.

Telling people they are wrong strikes a direct blow at their intelligence, judgement, pride, self respect. makes them want to strike back.
– you won’t make them change their minds
– you won’t alter their opinions because this hurts them
– “I’m smarter than you are — I’m going to tell you a thing or two and make you change your mind”
– that’s a challenge, arouses opposition and makes listener want to battle.
– If you’re going to prove anything don’t let anybody know it. do it so subtly, so adroitly, that nobody will feel that you are doing it.

Alexander Pope: Men must be taught as if you’d taught them not, and things unknown, proposed as things forgot.

Galileo: You can’t teach a man anything. You can only help him find it within himself.

Lord Chesterfield: Be wiser than other people if you can, but do not tell them so.

Socrates: One thing only I know, and that is that I know nothing.

Quit telling people that they are wrong.

“I may be wrong, I frequently am, let’s examine the facts”

“The mind in the making”

“my father”
“my country”
— my is a powerful-

7:00
– we like to continue to believe what we’ve always believed
– most arguments are made to go on believing as we already do.

TRACK 20:
Read about Benjamin Franklin’s autobiography.

Benjamin Franklin changes use of word “Certainly” to “I believe that…” etc.

making business proposition to bunch of bosses — couldn’t accept because you were telling someone that they are wrong. This makes you unwelcome part of discussion.

Martin Luther King:
“I judge people by their own principles, not my own”

PRINCIPLE 2: Show respect for the other person’s opinions. Never say “You’re wrong”.

TRACK 21: Chapter 3: If you’re wrong, admit it.

Dude takes a walk with his Boston bulldog without a leash or muzzle.

One day, encountered policeman in park that was itching to show his authority.

COP: “That’s against the law!”
MAN: “This little guy wouldn’t hurt anyone!”
COP: “He might! I’ll let you off, but never again.”

Later, policeman catches him again.

He beats the cop to it. “I’m sorry.”

e.g. case of a person who walked his dog in a park without a muzzle.
– week 1: caught. police officer rebukes.
– week 2: caught again, but condemns himself before police officer gets a chance to.
– result: police officer says man is being “too harsh” etc.
– police officer satisfies need to “feel important” by playing down the man’s mistake of walking dog w/o muzzle, where last week, he was considering it a great offense when the man tried to defend himself.

This tends to work with people with very high opinions of themselves and think themselves powerful.

“Isn’t it better to beat the other person to rebuking yourself?”

saying derogetory things about yourself that you know the other person is thinking/intending to say —
Likely, a generous forgiving attitude will be taken and you’ll look better.

4:00 art commissioner.
– very pick manager for art firm
– artist’s eagerness to criticise his own work
took all the fight out of the manager.

8:00 gives one a feeling of nobility and exultation to blame one’s self

Picket’s charge was the beginning of the end. The south was doomed.

Track 22:
– Michael Chaun: Chinese culture causes some problems w/ this system:
– in Chinese tradition, an older person cannot take the first step. this is a loss of face.
– When wrong, let’s admit our mistakes quickly and with enthusiasm. it is a lot more “fun” than trying to defend oneself

– “by fighting, you never get enough, but by yielding, you get more than you expected.”

PRINCIPLE 3: IF you are wrong, admit it quickly and emphatically

Track 23: Chapter 4: A drop of honey.

Woodrow Wilson: If you come at me with your fists doubled – mine will double too.

– This has Rockefeller’s attempt to create friends out of these people who hated him.

If a man is angry with you or hates you, you can’t win them to your side… unless you lead them to by being friendly to them.

Lincoln: “It is an old and true maxim that a drop of honey catches more flies than a gallon gall. So with men. If you would win a man to your cause, first convince him that you are his sincere friend. Therein is a drop of honey that catches his heart, which, say what you will, is the great high road to his reason.”

friendliness begets friendliness. was kind to striking laborours.

the sun can make you take off your coat more readily than the wind can.

PRINCIPLE 4: Begin in a friendly way

Writing good unit test cases is hard and requires you to be paying a lot of attention to catch problems.

Consider for example, this operator/ (vector division) method for a Vector class (NOT STRUCT!)

( Since class Vector is a class and not a struct, vec will be passed by reference. )


  public static Vector operator /( Vector vec, double divider )
  {
    vec.x /= divider;
    vec.y /= divider;

    return vec ;
  }

Above code to be used as in:

Vector v = new Vector( 15, 5 ) ;
Vector w = v / 5 ;

Can you see the bug?

You really have to be paying very close attention to ideas that the original programmer (frequently you) might have overlooked when developing the method.

Remember, Vector is a class, not a struct!

Here’s a naive first attempt at Unit test for the operator/ method:

    [TestMethod()]
    public void op_DivisionTest()
    {
      // make a vector and divide it by a constant
      Vector vec = new Vector( 4.92, 8 ) ;
      double d = 7.7 ;
      Vector actual = vec / d ;

      // Find what it should actually be:
      Vector expected = new Vector( 4.92/d, 8/d ) ;
      
      // Assert result is what you expect
      Assert.AreEqual( expected, actual );
            
    }

Can you see the problem? Can you see how this unit test FAILS to catch the real problem with this method?

Look again at the original operator/ method at the top of this page. The problem with the method is it mutates vec, since vec is passed by REFERENCE only and not by value (the method would be FINE if class Vector were struct Vector instead!

So, here’s the better unit test that catches this problem:

    [TestMethod()]
    public void op_DivisionTest()
    {
      // Compute a result, and find expected value as well
      Vector vec = new Vector( 4.92, 8 ) ;
      double d = 7.7 ;
      Vector actual = vec / d ;

      Vector expected = new Vector( 4.92/d, 8/d ) ;
      
      // Test result is what you expect:
      Assert.AreEqual( expected, actual );

      // This is "writing good unit tests".  TEST FURTHER.
      // What else should be guaranteed by this method / what
      // is the programmer to naturally assume about how the
      // method behaves and what it does to its inputs?

      // 1.  A new object, distinct instance of an object should be produced.
      Assert.AreNotSame( vec, actual ) ;
      
      // 2.  vec should remain unchanged from its original value
      Assert.AreEqual( vec, new Vector( 4.92, 8 ) ) ;
      
    }

The corrected operator/ method

For instance, here is an operator/ division method for a Vector class (NOT STRUCT!)
  public static Vector operator /( Vector vec, double divider )
  {
    Vector result = new Vector() ;

    result.x = vec.x / divider;
    result.y = vec.y / divider;

    return result ;
  }

So its easy to write crummy simple unit tests that don’t catch everything!! Unit tests aren’t catch-all.. you have to write them cleverly!

C++ is like C#, only it allows you a great deal more fine tuning than C# does.

I like how in C++:

  • its easy to create a class that has pass-by-value semantics at times, AND pass-by-reference semantics at other times. Thinking of a Matrix class.
  • Const Functions

I recently discovered you can use an implicit operator (TYPENAME) to make implicit conversions happen automatically for your custom types in C#:

public class Vector
{

  public static implicit operator string( Vector v )
  {
    return v.ToString() ;
  }

}

Now you can

Vector v = new Vector();
Console.WriteLine( v ) ;

Instead of

Vector v = new Vector();
Console.WriteLine( v.ToString() ) ;

So, at first I thought, WOW! That’s great. I’m developing a Matrix and Vector class together and its nice to be able to convert the Vector to a System.Drawing.PointF automatically, so instead of defining a property like:

public class Vector
{

  public System.Drawing.PointF PointF{ get {
    return new System.Drawing.PointF( this.x, this.y ) ;
  } }

}

For use in

Vector v = new Vector( 5, 7 ) ;
graphics.FillEllipse( v.PointF, 10 ) ;

I can now:

public class Vector
{

  public static implicit operator System.Drawing.PointF( Vector v )
  {
    return new System.Drawing.PointF( v.x, v.y ) ;
  }

}

So we could actually

Vector v = new Vector( 5, 7 ) ;
graphics.FillEllipse( v, 10 ) ;  // IMPLICIT TYPE CONVERSION
// TO POINTF NOW SUPPORTED!!

So that’s nice.

BUT.

What’s NOT NICE is what the compiler does when you define an implicit operator THAT ALSO has the == operator DEFINED FOR IT, but your class does not.

So, guess what happens if I DON’T define operator== for my Vector class, but I have the implicit operator string defined as shown above?

GUESS WHAT HAPPENS???

Vector v1 = new Vector( 5, 7 );
Vector v2 = new Vector( 5, 7 ) ;
if( v1 == v2 )  // v1 AND v2 ARE CONVERTED TO STRINGS, THEN COMPARED!!
{
}

This is AWFUL!! Instead of the compiler flagging it now, with “operator not defined for type Vector” (as it would have if we didn’t define implicit operator string), the compiler merrily compiles it!

THIS IS BAD!! Not even mentioning efficiency, in my ToString() method, there’s a round off leaving only 2 decimals! This means that 2.581 and 2.589999 are EQUAL in my program right now!!

Bad! BAD .NET!! BAD!!!!!!!!

Mine is:

public static implicit operator string( object o )
{
  ...
}

On Rotation Matrices

A common problem you come across is GIVEN a vector describing a “look” direction, HOW CAN WE MAKE A ROTATION MATRIX THAT WILL “LINE UP” WITH IT? You often want to do something like this when you have a character model that you need to rotate to line up with the direction that the character is currently facing. For example, you are writing a 3d space simulator game and you need the ship’s model to be lined up precisely with the direction the ship is facing.

It turns out, this is easy to do. So easy to do in fact, you’ll kick yourself for not having known this. But it isn’t easy to understand how it works.

So, first, let’s understand the principles of what we’re doing here in 2d, then we’ll extend our answer to 3d.

Rotating something to line up with an object in 2d

Assume you work in a world of vectors. In your 2d game, you need to have the model of your character point in the direction that he is looking.

Have: (red arrow is direction the Triangle character is looking).

But the black triangle and black arrow indicate the stock direction the model faces.

Want:

The most obvious way to solve this problem is just a 2d rotation matrix.

Matrix that rotates a point t degrees counter-clockwise:

The Triangle starts with its Heading vector pointing (1, 0). What we need to do is rotate the Heading vector 60 degrees counter-clockwise.

To make a 60 degree CCW rotation, let’s use the CCW rotation matrix, plugging in 60 degrees for the rotation we want:

So we end up with this set of numbers that promise to rotate a set of points 60 degrees counterclockwise:

Now here’s another way to get that same matrix. Are you ready?

The red vector (which points in the direction we want to face) is called the forward vector. The blue vector, we’ll simply call the side vector. ASSUME BOTH THE forward AND side vectors are UNIT VECTORS (THIS IS VERY IMPORTANT!!)

Since we know the forward vector is a unit vector and it has a 60 degree angle with the x-axis, we can express it as:
xfwd = cos( 60 )
= 0.5

yfwd = sin( 60 )
= 0.86

So a unit vector in the plane, when broken down into its x, y components, is always going to be x=cos(t), y=sin(t) where t is the angle that the vector forms with the +x axis.

The blue vector makes (90+60=150) degree angle with the +x axis. So it can be expressed as:
xperpleft = cos( 150 )
= -0.86

yperpleft = sin( 150 )
= 0.5

So, speaking in terms of the orientation we want, we have two vectors:

forward (describes direction we want to look in)=( 0.5, 0.86 )
perpleft (90 degrees counter-clockwise perpendicular to the forward vector) = ( -0.86, 0.5 )

We could also derive the perpleft vector by noticing that ( -y, x ) is always going to be a 90 degree counter-clockwise rotated perpendicular to any vector you have.

side note:
You are sure that (-y,x) is a perpendicular to (x,y) because the dot product:
(x,y)*(-y,x) = -yx + xy = 0

and so, (-y,x) is always perpendicular to (x,y).

The other way to derive this is to construct the 90 degree CCW rotation matrix and notice that it always comes out to

[ cos(90)   -sin(90) ] [ x ]
[ sin(90)    cos(90) ] [ y ]

[ 0   -1 ] [ x ] = [ -y ]
[ 1    0 ] [ y ]   [  x ]

So, look at those again:

forward: ( 0.5, 0.86 )
perpleft: ( -0.86, 0.5 )

Does that look familiar?

So we can do this:

Assuming you use column vectors and not row vectors. If you’re using row vectors, you have to transpose it.

Isn’t that neat?

This extends to 3D:

At this point, I’ll direct you to Diana Gruber’s article and leave it at that.

You know what makes me mad? System.Windows.Media.Matrix.Transform( System.Windows.Vector ) ACTUALLY IGNORES the translation component.

To get System.Windows.Media.Matrix.Transform to take into account the translation component, you have to pass it a System.Windows.Point, and NOT a System.Windows.Vector.

I want to use System.Windows.Vector for the operator overloading. So this is really inconvenient. After every transformation I have to remember to write

// vecs is an array of Vector[]
matTransform.Transform( vecs ) ;

// Microsoft dumbness:  Matrix.Transform( Vector ) does not apply
// the translation component, so we have to apply it ourselves
for( int i = 0 ; i < vecs.Length ; i ++ )
{
  vecs[ i ].X += matTransform.OffsetX ;
  vecs[ i ].Y += matTransform.OffsetY ;
}

This seems so dumb and unintuitive to me. Yes, a “vector” is being distinguished from a “point” by the idea that a vector is just a magnitude and direction without having an absolute position in space, while a “point” describes a point in space, but PRACTICALLY, this isn’t how I’d think to use it. The System.Drawing.Matrix was a lot smarter, with a System.Drawing.Matrix.TransformPoints method (correctly applies translation) AND a System.Drawing.Matrix.TransformVectors method, in case you want stupid unintuitive behavior of ignoring the translation component.

Its not even documented that this is how System.Windows.Media.Matrix behaves (they must be too embarrassed to admit it, no), you have to infer it from the old version of the documentation.

It makes me so mad because WHY WOULD I EVER want a matrix translation component not to be applied? Me, I’d simply zero out Matrix.OffsetX and Matrix.OffsetY before applying the transformation if I wanted that part to be ignored. I’m used to working in 3D where the transformation matrix is simply applied to the vectors, OBVIOUSLY applying the translation component. It just doesn’t make intuitive sense to me to have VECTORS ignore the translation component.

I see this as a HUGE defect in the library, ESPECIALLY since differing behavior is determined by OVERLOAD.. it just seems SO stupid and unintuitive. Another one for never put a sock in a toaster..

Overloads should DO THE EXACT SAME THING, only on different types of inputs. If you want functions that do different things, then do it right and write two separate functions.

How to programmatically raise an event in C#

Some say you can’t.

Other repeatedly and annoyingly say “just call the callback manually, and pass (null, null) for the args”.

Other still find the answer is YOU CAN!!

So, for a Button:

button1.PerformClick() ;

The form itself has a whole series of functions…

this.OnClick( ... );
this.OnClientSizeChanged( ... ) ;

// And
this.RaiseMouseEvent( ... ) ; // (pretty much) undocumented. nobody seems to know how to use this one!

There’s also this REALLY COMPLICATED way using Interop and the SendMessage() WinAPI function. You don’t have to go there though.

default inside a class is private

I think its time to get away from Courier New

Now I’m onto Bitstream Vera Sans Mono!

The filenames of this font are “VeraMoBd.ttf”, “VeraMoBI.ttf”, “VeraMoIt.ttf”, “VeraMono.ttf”

_M_CEE_PURE

fatal error C1083: Cannot open include file: ‘wx/setup.h’: No such file or directory c:\wxwidgets-2.8.10\include\wx\platform.h 196

Solve this by adding C:\wxWidgets-2.8.10\include\msvc to your Visual Studio path settings.

Cannot open include file: ‘../../../lib/vc_lib/mswd/wx/setup.h’: No such file or directory C:\wxWidgets-2.8.10\include\msvc\wx\setup.h

“Obviously you need to build wxwidgets first”

The dsw workspace is in C:\wxWidgets-2.8.10\build\msw

Its not that hard:


using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

using System;
using System.Runtime.InteropServices;


public class MainWindow : Form
{
  static Bitmap backbuffer;
  
  const int windowWidth = 640;
  const int windowHeight = 480;

  static int a = 5;

  public MainWindow()
  {
    this.ClientSize = new Size( windowWidth, windowHeight );

    // The OptimizedDoubleBuffer style has no effect due to the way
    // we control this game (drawing would have to be in OnPaint for
    // it to benefit us at all.)
    this.SetStyle( ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.Opaque, true );

    // Create the backbuffer
    backbuffer = new Bitmap( windowWidth, windowHeight );
  }

  public void Render()
  {
    Graphics g = Graphics.FromImage( backbuffer );

    // clear the background.  normally if you weren't using a
    // backbuffer, this would cause severe flicker.
    g.Clear( Color.White );

    // just draw something.  a line that moves
    a++;
    g.DrawLine( new Pen( Color.Blue, 5 ), new Point( 5, 5 ), new Point( a, 500 ) );


    // Flip the backbuffer
    Graphics gFrontBuffer = Graphics.FromHwnd( this.Handle );
    gFrontBuffer.DrawImage( backbuffer, new Point( 0, 0 ) );
  }

  // We're not painting in OnPaint().
  /* protected override void OnPaint( PaintEventArgs e ) { } */

  static void Main()
  {
    // why not to use while(Created){FullRender();Application.DoEvents();}
    //http://blogs.msdn.com/tmiller/archive/2003/11/07/57524.aspx

    // Also here are records of people burned by it (scroll to bottom)
    //http://msdn.microsoft.com/en-us/library/system.windows.forms.application.doevents.aspx

    // alternative approaches to DoEvents loop
    //http://blogs.msdn.com/tmiller/archive/2003/11/24/57532.aspx

    // Using traditional PeekMessage() loop

    // Create-up a window.
    MainWindow mw = new MainWindow();
    mw.Show();
    // (style init stuff is in its constructor)

    Win32.NativeMessage msg = new Win32.NativeMessage();

    while( true )
    {
      if( !mw.Created )
      {
        // Need this here for the application to shutdown gracefully.
        break;
      }

      if( Win32.PeekMessage( out msg, mw.Handle, 0, 0, (uint)Win32.PM.REMOVE ) )
      {
        if( msg.message == (uint)Win32.WindowsMessage.WM_QUIT )
        {
          Console.WriteLine( "QUITTING..." );
          break;
        }
        else
        {
          Win32.TranslateMessage( ref msg );
          Win32.DispatchMessage( ref msg );
        }

      }

      else
      {

        // Run the game simulation

        // Render current state
        mw.Render();

        System.Threading.Thread.Sleep( 2 );

      }

    }

    Application.Exit();

  }
}


public static class Win32
{
  // From http://www.pinvoke.net/default.aspx/user32/PeekMessage.html
  [StructLayout( LayoutKind.Sequential )]
  public struct NativeMessage
  {
    public IntPtr hwnd;
    public uint message;
    public IntPtr wParam;
    public IntPtr lParam;
    public uint time;
    public System.Drawing.Point point;
  }

  [DllImport( "user32.dll" )]
  [return: MarshalAs( UnmanagedType.Bool )]
  public static extern bool PeekMessage( out NativeMessage lpMsg, IntPtr hwnd, uint wMsgFilterMin, uint wMsgFilterMax, uint wRemoveMsg );

  public enum PM : uint
  {
    NOREMOVE = 0,
    REMOVE = 1
  }

  [DllImport( "user32.dll" )]
  public static extern bool TranslateMessage( [In] ref NativeMessage lpMsg );

  [DllImport( "user32.dll" )]
  public static extern IntPtr DispatchMessage( [In] ref NativeMessage lpmsg );

  #region all the sys metrics and WM_ windows message defs
  // from winuser.h
  /*
   * GetSystemMetrics() codes
   */
  public enum SystemMetrics : uint
  {
    SM_CXSCREEN = 0,
    SM_CYSCREEN = 1,
    SM_CXVSCROLL = 2,
    SM_CYHSCROLL = 3,
    SM_CYCAPTION = 4,
    SM_CXBORDER = 5,
    SM_CYBORDER = 6,
    SM_CXDLGFRAME = 7,
    SM_CXFIXEDFRAME = 7,/* ;win40 name change */
    SM_CYDLGFRAME = 8,
    SM_CYFIXEDFRAME = 8,/* ;win40 name change */
    SM_CYVTHUMB = 9,
    SM_CXHTHUMB = 10,
    SM_CXICON = 11,
    SM_CYICON = 12,
    SM_CXCURSOR = 13,
    SM_CYCURSOR = 14,
    SM_CYMENU = 15,
    SM_CXFULLSCREEN = 16,
    SM_CYFULLSCREEN = 17,
    SM_CYKANJIWINDOW = 18,
    SM_MOUSEPRESENT = 19,
    SM_CYVSCROLL = 20,
    SM_CXHSCROLL = 21,
    SM_DEBUG = 22,
    SM_SWAPBUTTON = 23,
    SM_RESERVED1 = 24,
    SM_RESERVED2 = 25,
    SM_RESERVED3 = 26,
    SM_RESERVED4 = 27,
    SM_CXMIN = 28,
    SM_CYMIN = 29,
    SM_CXSIZE = 30,
    SM_CYSIZE = 31,
    SM_CXFRAME = 32,
    SM_CXSIZEFRAME = 32, /* ;win40 name change */
    SM_CYFRAME = 33,
    SM_CYSIZEFRAME = 33,/* ;win40 name change */
    SM_CXMINTRACK = 34,
    SM_CYMINTRACK = 35,
    SM_CXDOUBLECLK = 36,
    SM_CYDOUBLECLK = 37,
    SM_CXICONSPACING = 38,
    SM_CYICONSPACING = 39,
    SM_MENUDROPALIGNMENT = 40,
    SM_PENWINDOWS = 41,
    SM_DBCSENABLED = 42,
    SM_CMOUSEBUTTONS = 43,
    SM_SECURE = 44,
    SM_CXEDGE = 45,
    SM_CYEDGE = 46,
    SM_CXMINSPACING = 47,
    SM_CYMINSPACING = 48,
    SM_CXSMICON = 49,
    SM_CYSMICON = 50,
    SM_CYSMCAPTION = 51,
    SM_CXSMSIZE = 52,
    SM_CYSMSIZE = 53,
    SM_CXMENUSIZE = 54,
    SM_CYMENUSIZE = 55,
    SM_ARRANGE = 56,
    SM_CXMINIMIZED = 57,
    SM_CYMINIMIZED = 58,
    SM_CXMAXTRACK = 59,
    SM_CYMAXTRACK = 60,
    SM_CXMAXIMIZED = 61,
    SM_CYMAXIMIZED = 62,
    SM_NETWORK = 63,
    SM_CLEANBOOT = 67,
    SM_CXDRAG = 68,
    SM_CYDRAG = 69,

    SM_SHOWSOUNDS = 70,
    SM_CXMENUCHECK = 71,   /* Use instead of GetMenuCheckMarkDimensions()! */
    SM_CYMENUCHECK = 72,
    SM_SLOWMACHINE = 73,
    SM_MIDEASTENABLED = 74,
    SM_MOUSEWHEELPRESENT = 75,
    SM_XVIRTUALSCREEN = 76,
    SM_YVIRTUALSCREEN = 77,
    SM_CXVIRTUALSCREEN = 78,
    SM_CYVIRTUALSCREEN = 79,
    SM_CMONITORS = 80,
    SM_SAMEDISPLAYFORMAT = 81,
    SM_IMMENABLED = 82,
    SM_CXFOCUSBORDER = 83,
    SM_CYFOCUSBORDER = 84,

    SM_TABLETPC = 86,
    SM_MEDIACENTER = 87,
    SM_STARTER = 88,
    SM_SERVERR2 = 89,
    SM_CMETRICS = 90,
    SM_REMOTESESSION = 0x1000,
    SM_SHUTTINGDOWN = 0x2000,
    SM_REMOTECONTROL = 0x2001,
    SM_CARETBLINKINGENABLED = 0x2002

  }










  public enum WindowsMessage : uint
  {
    /*
     * Window Messages
     */

    WM_NULL = 0x0000,
    WM_CREATE = 0x0001,
    WM_DESTROY = 0x0002,
    WM_MOVE = 0x0003,
    WM_SIZE = 0x0005,

    WM_ACTIVATE = 0x0006,

    WM_SETFOCUS = 0x0007,
    WM_KILLFOCUS = 0x0008,
    WM_ENABLE = 0x000A,
    WM_SETREDRAW = 0x000B,
    WM_SETTEXT = 0x000C,
    WM_GETTEXT = 0x000D,
    WM_GETTEXTLENGTH = 0x000E,
    WM_PAINT = 0x000F,
    WM_CLOSE = 0x0010,

    //#ifndef _WIN32_WCE
    WM_QUERYENDSESSION = 0x0011,
    WM_QUERYOPEN = 0x0013,
    WM_ENDSESSION = 0x0016,
    //#endif
    WM_QUIT = 0x0012,
    WM_ERASEBKGND = 0x0014,
    WM_SYSCOLORCHANGE = 0x0015,
    WM_SHOWWINDOW = 0x0018,
    WM_WININICHANGE = 0x001A,

    WM_DEVMODECHANGE = 0x001B,
    WM_ACTIVATEAPP = 0x001C,
    WM_FONTCHANGE = 0x001D,
    WM_TIMECHANGE = 0x001E,
    WM_CANCELMODE = 0x001F,
    WM_SETCURSOR = 0x0020,
    WM_MOUSEACTIVATE = 0x0021,
    WM_CHILDACTIVATE = 0x0022,
    WM_QUEUESYNC = 0x0023,

    WM_GETMINMAXINFO = 0x0024,

    WM_PAINTICON = 0x0026,
    WM_ICONERASEBKGND = 0x0027,
    WM_NEXTDLGCTL = 0x0028,
    WM_SPOOLERSTATUS = 0x002A,
    WM_DRAWITEM = 0x002B,
    WM_MEASUREITEM = 0x002C,
    WM_DELETEITEM = 0x002D,
    WM_VKEYTOITEM = 0x002E,
    WM_CHARTOITEM = 0x002F,
    WM_SETFONT = 0x0030,
    WM_GETFONT = 0x0031,
    WM_SETHOTKEY = 0x0032,
    WM_GETHOTKEY = 0x0033,
    WM_QUERYDRAGICON = 0x0037,
    WM_COMPAREITEM = 0x0039,
    WM_COMPACTING = 0x0041,
    WM_COMMNOTIFY = 0x0044,  /* no longer suported */
    WM_WINDOWPOSCHANGING = 0x0046,
    WM_WINDOWPOSCHANGED = 0x0047,

    WM_POWER = 0x0048,
    /*
     * wParam for WM_POWER window message and DRV_POWER driver notification
    #define PWR_OK              1
    #define PWR_FAIL            (-1)
    #define PWR_SUSPENDREQUEST  1
    #define PWR_SUSPENDRESUME   2
    #define PWR_CRITICALRESUME  3
     */

    WM_COPYDATA = 0x004A,
    WM_CANCELJOURNAL = 0x004B,


    /*
     * lParam of WM_COPYDATA message points to...
    typedef struct tagCOPYDATASTRUCT {
        ULONG_PTR dwData;
        DWORD cbData;
        PVOID lpData;
    } COPYDATASTRUCT, *PCOPYDATASTRUCT;
     */

    //#if(WINVER >= 0x0400)
    WM_NOTIFY = 0x004E,
    WM_INPUTLANGCHANGEREQUEST = 0x0050,
    WM_INPUTLANGCHANGE = 0x0051,
    WM_TCARD = 0x0052,
    WM_HELP = 0x0053,
    WM_USERCHANGED = 0x0054,
    WM_NOTIFYFORMAT = 0x0055,

    WM_CONTEXTMENU = 0x007B,
    WM_STYLECHANGING = 0x007C,
    WM_STYLECHANGED = 0x007D,
    WM_DISPLAYCHANGE = 0x007E,
    WM_GETICON = 0x007F,
    WM_SETICON = 0x0080,
    //#endif /* WINVER >= 0x0400 */

    WM_NCCREATE = 0x0081,
    WM_NCDESTROY = 0x0082,
    WM_NCCALCSIZE = 0x0083,
    WM_NCHITTEST = 0x0084,
    WM_NCPAINT = 0x0085,
    WM_NCACTIVATE = 0x0086,
    WM_GETDLGCODE = 0x0087,
    //#ifndef _WIN32_WCE
    WM_SYNCPAINT = 0x0088,
    //#endif
    WM_NCMOUSEMOVE = 0x00A0,
    WM_NCLBUTTONDOWN = 0x00A1,
    WM_NCLBUTTONUP = 0x00A2,
    WM_NCLBUTTONDBLCLK = 0x00A3,
    WM_NCRBUTTONDOWN = 0x00A4,
    WM_NCRBUTTONUP = 0x00A5,
    WM_NCRBUTTONDBLCLK = 0x00A6,
    WM_NCMBUTTONDOWN = 0x00A7,
    WM_NCMBUTTONUP = 0x00A8,
    WM_NCMBUTTONDBLCLK = 0x00A9,



    //#if(_WIN32_WINNT >= 0x0500)
    WM_NCXBUTTONDOWN = 0x00AB,
    WM_NCXBUTTONUP = 0x00AC,
    WM_NCXBUTTONDBLCLK = 0x00AD,
    //#endif /* _WIN32_WINNT >= 0x0500 */


    //#if(_WIN32_WINNT >= 0x0501)
    WM_INPUT = 0x00FF,
    //#endif /* _WIN32_WINNT >= 0x0501 */

    WM_KEYFIRST = 0x0100,
    WM_KEYDOWN = 0x0100,
    WM_KEYUP = 0x0101,
    WM_CHAR = 0x0102,
    WM_DEADCHAR = 0x0103,
    WM_SYSKEYDOWN = 0x0104,
    WM_SYSKEYUP = 0x0105,
    WM_SYSCHAR = 0x0106,
    WM_SYSDEADCHAR = 0x0107,
    //#if(_WIN32_WINNT >= 0x0501)
    WM_UNICHAR = 0x0109,
    WM_KEYLAST = 0x0109,
    //#define UNICODE_NOCHAR                  0xFFFF

    //#if(WINVER >= 0x0400)
    WM_IME_STARTCOMPOSITION = 0x010D,
    WM_IME_ENDCOMPOSITION = 0x010E,
    WM_IME_COMPOSITION = 0x010F,
    WM_IME_KEYLAST = 0x010F,
    //#endif /* WINVER >= 0x0400 */

    WM_INITDIALOG = 0x0110,
    WM_COMMAND = 0x0111,
    WM_SYSCOMMAND = 0x0112,
    WM_TIMER = 0x0113,
    WM_HSCROLL = 0x0114,
    WM_VSCROLL = 0x0115,
    WM_INITMENU = 0x0116,
    WM_INITMENUPOPUP = 0x0117,
    WM_MENUSELECT = 0x011F,
    WM_MENUCHAR = 0x0120,
    WM_ENTERIDLE = 0x0121,
    //#if(WINVER >= 0x0500)
    //#ifndef _WIN32_WCE
    WM_MENURBUTTONUP = 0x0122,
    WM_MENUDRAG = 0x0123,
    WM_MENUGETOBJECT = 0x0124,
    WM_UNINITMENUPOPUP = 0x0125,
    WM_MENUCOMMAND = 0x0126,

    //#ifndef _WIN32_WCE
    //#if(_WIN32_WINNT >= 0x0500)
    WM_CHANGEUISTATE = 0x0127,
    WM_UPDATEUISTATE = 0x0128,
    WM_QUERYUISTATE = 0x0129,

    WM_CTLCOLORMSGBOX = 0x0132,
    WM_CTLCOLOREDIT = 0x0133,
    WM_CTLCOLORLISTBOX = 0x0134,
    WM_CTLCOLORBTN = 0x0135,
    WM_CTLCOLORDLG = 0x0136,
    WM_CTLCOLORSCROLLBAR = 0x0137,
    WM_CTLCOLORSTATIC = 0x0138,
    //#define MN_GETHMENU                     0x01E1

    WM_MOUSEFIRST = 0x0200,
    WM_MOUSEMOVE = 0x0200,
    WM_LBUTTONDOWN = 0x0201,
    WM_LBUTTONUP = 0x0202,
    WM_LBUTTONDBLCLK = 0x0203,
    WM_RBUTTONDOWN = 0x0204,
    WM_RBUTTONUP = 0x0205,
    WM_RBUTTONDBLCLK = 0x0206,
    WM_MBUTTONDOWN = 0x0207,
    WM_MBUTTONUP = 0x0208,
    WM_MBUTTONDBLCLK = 0x0209,
    //#if (_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)
    WM_MOUSEWHEEL = 0x020A,
    //#endif
    //#if (_WIN32_WINNT >= 0x0500)
    WM_XBUTTONDOWN = 0x020B,
    WM_XBUTTONUP = 0x020C,
    WM_XBUTTONDBLCLK = 0x020D,
    //#endif
    //#if (_WIN32_WINNT >= 0x0500)
    WM_MOUSELAST = 0x020D,


    //#if(_WIN32_WINNT >= 0x0400)
    /* Value for rolling one detent */
    //#define WHEEL_DELTA                     120
    //#define GET_WHEEL_DELTA_WPARAM(wParam)  ((short)HIWORD(wParam))

    /* Setting to scroll one page for SPI_GET/SETWHEELSCROLLLINES */
    //#define WHEEL_PAGESCROLL                (UINT_MAX)
    //#endif /* _WIN32_WINNT >= 0x0400 */

    WM_PARENTNOTIFY = 0x0210,
    WM_ENTERMENULOOP = 0x0211,
    WM_EXITMENULOOP = 0x0212,

    //#if(WINVER >= 0x0400)
    WM_NEXTMENU = 0x0213,
    WM_SIZING = 0x0214,
    WM_CAPTURECHANGED = 0x0215,
    WM_MOVING = 0x0216,
    //#endif /* WINVER >= 0x0400 */

    //#if(WINVER >= 0x0400)
    WM_POWERBROADCAST = 0x0218,
    /*
    #ifndef _WIN32_WCE
    #define PBT_APMQUERYSUSPEND             0x0000
    #define PBT_APMQUERYSTANDBY             0x0001

    #define PBT_APMQUERYSUSPENDFAILED       0x0002
    #define PBT_APMQUERYSTANDBYFAILED       0x0003

    #define PBT_APMSUSPEND                  0x0004
    #define PBT_APMSTANDBY                  0x0005

    #define PBT_APMRESUMECRITICAL           0x0006
    #define PBT_APMRESUMESUSPEND            0x0007
    #define PBT_APMRESUMESTANDBY            0x0008

    #define PBTF_APMRESUMEFROMFAILURE       0x00000001

    #define PBT_APMBATTERYLOW               0x0009
    #define PBT_APMPOWERSTATUSCHANGE        0x000A

    #define PBT_APMOEMEVENT                 0x000B
    #define PBT_APMRESUMEAUTOMATIC          0x0012
    #endif
    */
    //#endif /* WINVER >= 0x0400 */

    //#if(WINVER >= 0x0400)
    WM_DEVICECHANGE = 0x0219,
    //#endif /* WINVER >= 0x0400 */

    WM_MDICREATE = 0x0220,
    WM_MDIDESTROY = 0x0221,
    WM_MDIACTIVATE = 0x0222,
    WM_MDIRESTORE = 0x0223,
    WM_MDINEXT = 0x0224,
    WM_MDIMAXIMIZE = 0x0225,
    WM_MDITILE = 0x0226,
    WM_MDICASCADE = 0x0227,
    WM_MDIICONARRANGE = 0x0228,
    WM_MDIGETACTIVE = 0x0229,


    WM_MDISETMENU = 0x0230,
    WM_ENTERSIZEMOVE = 0x0231,
    WM_EXITSIZEMOVE = 0x0232,
    WM_DROPFILES = 0x0233,
    WM_MDIREFRESHMENU = 0x0234,


    //#if(WINVER >= 0x0400)
    WM_IME_SETCONTEXT = 0x0281,
    WM_IME_NOTIFY = 0x0282,
    WM_IME_CONTROL = 0x0283,
    WM_IME_COMPOSITIONFULL = 0x0284,
    WM_IME_SELECT = 0x0285,
    WM_IME_CHAR = 0x0286,
    //#endif /* WINVER >= 0x0400 */
    //#if(WINVER >= 0x0500)
    WM_IME_REQUEST = 0x0288,
    //#endif /* WINVER >= 0x0500 */
    //#if(WINVER >= 0x0400)
    WM_IME_KEYDOWN = 0x0290,
    WM_IME_KEYUP = 0x0291,
    //#endif /* WINVER >= 0x0400 */

    //#if((_WIN32_WINNT >= 0x0400) || (WINVER >= 0x0500))
    WM_MOUSEHOVER = 0x02A1,
    WM_MOUSELEAVE = 0x02A3,
    //#endif
    //#if(WINVER >= 0x0500)
    WM_NCMOUSEHOVER = 0x02A0,
    WM_NCMOUSELEAVE = 0x02A2,
    //#endif /* WINVER >= 0x0500 */

    //#if(_WIN32_WINNT >= 0x0501)
    WM_WTSSESSION_CHANGE = 0x02B1,

    WM_TABLET_FIRST = 0x02c0,
    WM_TABLET_LAST = 0x02df,
    //#endif /* _WIN32_WINNT >= 0x0501 */

    WM_CUT = 0x0300,
    WM_COPY = 0x0301,
    WM_PASTE = 0x0302,
    WM_CLEAR = 0x0303,
    WM_UNDO = 0x0304,
    WM_RENDERFORMAT = 0x0305,
    WM_RENDERALLFORMATS = 0x0306,
    WM_DESTROYCLIPBOARD = 0x0307,
    WM_DRAWCLIPBOARD = 0x0308,
    WM_PAINTCLIPBOARD = 0x0309,
    WM_VSCROLLCLIPBOARD = 0x030A,
    WM_SIZECLIPBOARD = 0x030B,
    WM_ASKCBFORMATNAME = 0x030C,
    WM_CHANGECBCHAIN = 0x030D,
    WM_HSCROLLCLIPBOARD = 0x030E,
    WM_QUERYNEWPALETTE = 0x030F,
    WM_PALETTEISCHANGING = 0x0310,
    WM_PALETTECHANGED = 0x0311,
    WM_HOTKEY = 0x0312,

    //#if(WINVER >= 0x0400)
    WM_PRINT = 0x0317,
    WM_PRINTCLIENT = 0x0318,
    //#endif /* WINVER >= 0x0400 */

    //#if(_WIN32_WINNT >= 0x0500)
    WM_APPCOMMAND = 0x0319,
    //#endif /* _WIN32_WINNT >= 0x0500 */

    //#if(_WIN32_WINNT >= 0x0501)
    WM_THEMECHANGED = 0x031A,
    //#endif /* _WIN32_WINNT >= 0x0501 */


    //#if(WINVER >= 0x0400)

    WM_HANDHELDFIRST = 0x0358,
    WM_HANDHELDLAST = 0x035F,

    WM_AFXFIRST = 0x0360,
    WM_AFXLAST = 0x037F,
    //#endif /* WINVER >= 0x0400 */

    WM_PENWINFIRST = 0x0380,
    WM_PENWINLAST = 0x038F,


    //#if(WINVER >= 0x0400)
    WM_APP = 0x8000,
    //#endif /* WINVER >= 0x0400 */


    /*
     * NOTE: All Message Numbers below 0x0400 are RESERVED.
     *
     * Private Window Messages Start Here:
     */
    WM_USER = 0x0400
  }

  #endregion

}


Add assembly PresentationCore.

Was looking for that for 5 minutes man..

You have to override OnPaint.
I tried doing this:

using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;


namespace testnamespace
{

public class MainWindow : Form
{
  public static int a = 5 ;

  public MainWindow()
  {
    
    this.SetStyle( ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.Opaque, true ) ;

  }

  public void Render()
  {

    // NOT DOUBLE BUFFERED!  because
    // its not in OnPaint.
    Graphics g = Graphics.FromHwnd( this.Handle ) ;
    g.Clear( Color.White ) ;
    a++;

    g.DrawLine( new Pen( Color.Blue, 5 ), new Point( 5, 5 ), new Point( a, 500 )  );
   
  }

  protected override void OnPaint( PaintEventArgs e )
  {
    
    // THIS IS double buffered
    Graphics g = e.Graphics;

    g.Clear( Color.White );
    a++;

    g.DrawLine( new Pen( Color.Blue, 5 ), new Point( 5, 5 ), new Point( a, 500 ) );
    
    this.Invalidate();
    //base.OnPaint( e );
  }

  static void Main()
  {
    // why not to use while(Created){FullRender();Application.DoEvents();}
    //http://blogs.msdn.com/tmiller/archive/2003/11/07/57524.aspx

    // Also here are records of people burned by it (scroll to bottom)
    //http://msdn.microsoft.com/en-us/library/system.windows.forms.application.doevents.aspx

    // alternative approaches to DoEvents loop
    //http://blogs.msdn.com/tmiller/archive/2003/11/24/57532.aspx

    // Using traditional PeekMessage() loop
    
    // Create-up a window.
    MainWindow mw = new MainWindow();
    mw.Show();
    // (style init stuff is in its constructor)

    Win32.NativeMessage msg = new Win32.NativeMessage() ;

    Dictionary dic = EnumHelper.ReverseEnumLookup();

    while( true ) 
    {
      if( !mw.Created )
      {
        // Need this here for the application to shutdown gracefully.
        break ;
      }

      if( Win32.PeekMessage( out msg, mw.Handle, 0, 0, (uint)Win32.PM.REMOVE ) )
      {
        int msgId = (int)msg.message ;

        Console.WriteLine("MESSAGE!! " + msgId ) ;

        if( dic.ContainsKey( msgId ) )
          Console.WriteLine( "That's " + dic[msgId] ) ;
        else
          Console.WriteLine( "Unknown message!");

        if( msg.message == (uint)Win32.WindowsMessage.WM_QUIT )
        {
          Console.WriteLine("QUITTING...");
          break ;
        }
        else
        {
          Win32.TranslateMessage( ref msg ) ;
          Win32.DispatchMessage ( ref msg ) ;
        }

      }
      
      else
      {

        // Run the game simulation

        // Render current state
        mw.Render();
        
        System.Threading.Thread.Sleep( 2 );
      }
      
    }

    Application.Exit();

  }
}

  
}

But windows won’t double buffer anything you draw unless its in the OnPaint method.

I do this for win32 enums when I feel like it.

Set Visual studio find & replace to "USE: REGULAR EXPRESSIONS"

Find field:
[#]define[:b]+{WM_[A-Z]+}[:b]+{[0][x][0-9A-F]+}

Replace field:
\1 = \2,

Just like that

~page 140 of charles petzold’s Programming windows with C# has a description and example of reflection

he says that

REFLECTION is the process where

the DLL isn’t just a bunch of code. It exists with binary metadata that describes in detail the classes implemented in the file and all the fields, properties, methods and events in these classes. In fact, the C# compiler uses this information to compile programs (that’s why you ned to set the Reference files), and the reference documentation of the .NET framework is derived from this metadata.

So it makes sense that a program might be able to access this metadat at runtime, find out about the .NET classes dynamically, and even execute some methods and properties in them. This process is called reflection, and its a concept borrowed form Java.

Never Put A Sock In A Toaster

(~65:00 into the dvd)

A set of developer DUHs that I develop as I come across them in my own work

  • If you are setting some parameters that are specific to your dev machine, MARK machine specific settings with a comment //!!machine-specific. Before you try to run on another machine then, you can search for //!!mach and you will find all stuff you need to change.

    Origin is I set some parameters in an ogre app that were specific to my GPU. When I tried to run on another machine, it wouldn’t draw at all, and it said the error was coming “from ogre” (VERY generic exception). So it was a very hard bug to track down, and all the while you’re suspecting “maybe Ogre DOES have bugs”..

  • NEVER, please never, do a memset( this, 0, sizeof( SomeClass ) ) ; on any class or struct that inherits from some base class with virtual functions. You will zero out the virtual function pointers.
  • Don’t write member functions in your C++ code that mimic STL member functions. This leads to massive confusion. For example, some code I was reading recently had a class that wrapped TWO stl vectors (it needed them both internally). It them exposed 3 methods: .begin(), .end(), and .next() which were meant to help you iterate over the primary collection. The confusing part was USING this crap: was the class itself a std::vector? No. Then how/why does it have a .begin() and .end() method that looks EXACTLY as if the object WERE a vector? Second, it was confusing WHICH COLLECTION (as a user of the class) you would be iterating over. Remember the class had two collections.
  • Overloads should do the exact same thing to the inputs. For example, say you have two overloads: Matrix.Transform( Vector ) and Matrix.Transform( Point ). The only difference between Vector and Point practically is that Vector supports operator overloading.
    Now you would go and do something stupid like, I don’t know, make it so the translation elements of this matrix (third row) are ignored for Matrix.Transform( Vector ) and NOT for Matrix.Transform( Point ). No. That would be stupid and unintuitive, no? Well, that’s what Microsoft did.

    In the earlier System.Drawing namespace, (before Vector was created) they actually did this right, and provided 2 separate methods which both accepted Point only:

    TransformPoints Applies the geometric transform this Matrix represents to an array of points.
    TransformVectors Multiplies each vector in an array by the matrix. The translation elements of this matrix (third row) are ignored.
  • A math related one. If you happen to write a few matrix functions, PLEASE INDICATE WHETHER YOU ARE PREMULTIPLYING OR POSTMULTIPLYING vectors. Its important. If you created a matrix and intended it to be postmultiplied by a vector, but find out that the library wants to pre-multiply by the vector, you can just transpose your matrix before doing the multiply.
  • When working with angles that you increment (for example, you’re writing something with a spinny thing that goes round and round, with ever-increasing theta), make sure that the angle doesn’t get too big. In fact, its a good idea to regularly just

    // keep theta comfortably between -2*PI and 2*PI
    if( theta > 2*PI ) { theta -= 2*PI ; }
    else if( theta < -2*PI ) { theta += 2*PI ; }
    

    I once had a program that didn’t do this, and when theta got HUGE, the variable got corrupted and the graph looked REALLY weird. I saw the graph was fine, fine, fine, then sometime later it got twisted..

    so the problem was, theta was too big (duh!)

  • If you change the members of a structure or class, IMMEDIATELY UPDATE THE COPY CTOR OR PUT AN ASSERT IN THERE!
  • CHECK THE HRESULT OF EVERY COM OPERATION, NO MATTER WHAT, ALWAYS. A SMALL change can completely fuck up a perfectly good piece of code, and the COM failure can have happened literally HUNDREDS of lines of code before the symptom.
    ALWAYS check, and ALWAYS log the result, if not crash out and bail on fail.
  • Avoid stack allocated struct returns.

    For example, say you have a function

    STRUCT_TYPE initStruct()
    {
      STRUCT_TYPE t ;
      // .. do stuff
      return t ;
    }
    

    Then you call this by

    STRUCT_TYPE myStruct = initStruct() ;
    

    This is BAD because the return is by value. This means that the return t; statement:

    • Returns a COPY of t, and that is assigned to myStruct in the calling function
    • Then, DESTROYS t, invoking its destructor

    THIS IS BAD NEWS. Say STRUCT_TYPE has a destructor like:

    ~STRUCT_TYPE
    {
      delete[] array ;
    }
    

    Then what happens is, even though your returned a copy of STRUCT_TYPE, its internals might have been destroyed by the destructor call.

    So, write functions like this instead:

    void initStruct( STRUCT_TYPE & t )
    {
      // .. do stuff to t
    }
    

    Or:

    void initStruct( STRUCT_TYPE * t )
    {
      // .. do stuff to t
    }
    

    Or

    STRUCT_TYPE* initStruct()
    {
      STRUCT_TYPE * t = new STRUCT_TYPE ;
      // .. do stuff
      return t ;
    }
    
  • The first 2 examples don’t care how t is allocated, all they care is that t is allocated by the caller, so initStruct doesn’t decimate it when it returns and its scope ends.

    The last example heap allocates a STRUCT_TYPE object, so no destructor is invoked when t goes out of scope.

On Windows machines, almost every system I’ve seen starts with a C:\ drive.

You know, I still remember the days when the C:\ drive was new, and it was neat, because it meant you had a hard disk, which made this cool deep drilling sound when you accessed it.

A:\ and B:\ were the floppy disk drives. Usually you had something in the A:\ drive. When I was a kid, when we had the IBM PC Junior, if you wanted to play a game, you popped it into the A:\ drive and booted up. Digger was my favorite, then Styx.

I haven’t seen a machine with a floppy disk drive since… I don’t know when. Certainly not a NEW PC in well over 3-5 years now.

So machines today though, still start at C:\. Why? Well, the USB drive is removable.. its not a fixed thing, so it’d make little sense to make the “usb drive” A:\.

So what can you make A:\?

* CD/DVD-ram drive?
* primary hard disk partition!

I’d like to see, in the future, a 1G FAST “RAMDRIVE”. that’d be cool. when machines get ridiculous amounts of RAM (like 64G or something), you can allocate 2G of that RAM to an A:\ drive which gets wiped on computer shutdown. Its a GREAT scratch disk though – for putting stuff that you will only have there temporarily. Also it’d make a great recycling bin, requiring you to decided whether to delete or keep something on windows shutdown.

I personally just bought a new hard disk. And instead of making it E:\ or F:\, I decided to make it B:\. Hey! That’s new and unusual. I just couldn’t bring myself to make it A:\.

For a long time, I kept thinking “there is no point to a private variable if all you do is get/set it”

yeah yeah encapsulation encapsulation and whatever. But what if the get/set is just a pass-through? Surely its better in that case to use a public field.

HOWEVER. There is more to encapsulation

  • With the GET/SET, you remove “dependence” of your client on your field names. This means you have the OPPORTUNITY to change internally how you manage a variable. This makes it so your client (user of your class) DOES NOT NEED TO adjust his code, in case you need to change how a particular member is treated internally to your class

I made that mistake and my _vfptr was always 0 in the debugger!

It turns out that if you have:

class Object : public SomeInterfaceThatHasVirtualMemberFunctions
{
  int member1 ;
  float member2 ; 

public:
  Object()
  {
    // !! NEVER, EVER DO THIS!!  EVER!
    memset( this, 0, sizeof( Object ) )
  }
};

WHat happens is the v_table apparently gets 0’d out as well, not just the members.

UNRESOLVED EXTERNAL SYMBOL means that you’ve #included a header file that the C++ linker can’t find a BODY for. Usually it means you’re missing a .lib file, or it means that you have a .h file and you’ve neglected to implement a function body that’s mentioned in the .h file.

Needed the ogre command line tools, but thanks to this guy I was able to get it directly from the mirror service (which is really neat to browse too!)

http://www.mirrorservice.org/sites/download.sourceforge.net/pub/sourceforge/

The first thing you should know about an MFC app, as created by the Visual Studio wizard, is that there is a SINGLE, SUPERGLOBAL variable called theApp which is THE INSTANCE, the one and only instance, of your :CWndApp class.

You can access theApp from anywhere.

If using the SDI structure, then you can access ALL of the stuff in your application VIA theApp.

For example:
Anywhere in the application

    CWnd * main = theApp.GetMainWnd() ;
    CRuntimeClass * crtc = main->GetRuntimeClass() ;
    printf("The class is %s\n", crtc->m_lpszClassName );

    // make sure the window you got is of type CMainFrame.
    ASSERT( main->IsKindOf( CMainFrame::GetRuntimeClass() ) ) ;

    CMainFrame * mainframe = (CMainFrame*)main ;

    // now from here, we can access the treeview.
    wprintf( L"the window title is: %s\n", mainframe->GetTitle() ) ;


the mainframe member is now an instance of CMainFrame, so it has members to all the top level visible windows. e.g. in my CMainFrame.h file, I have:

protected:
	CClassView        m_wndClassView;
	COutputWnd        m_wndOutput;
	CPropertiesWnd    m_wndProperties;

You can either make these public or write accessor functions to return pointers to each.

Finally you can get the Document and View classes that the application is currently using by:

    CView* theView = mainframe->GetActiveView() ;
    crtc = theView->GetRuntimeClass() ; // remember, this only works
    // if your View class has DYN_CREATE assigned to it.

    printf(" The view class is %s\n", crtc->m_lpszClassName ) ;

    CDocument* theDoc = mainframe->GetActiveDocument() ;
    crtc = theDoc->GetRuntimeClass();
    printf(" The DOC class is %s\n", crtc->m_lpszClassName ) ;

So any and all of these is ANYWHERE ACCESSIBLE in mfc, since you ALWAYS have access to theApp. From theApp, you can get ANYTHING.

Another thing is sometimes GetRuntimeClass() doesn’t seem to work. If it seems to get the class name wrong, then you have to make sure that you add

DECLARE_DYNCREATE( CWhateverYourActualClassNameIsHere )

In the .h file and

IMPLEMENT_DYNCREATE( CWhateverYourActualClassNameIsHere , CWhateverItsBaseClassIs_GoesHere )

In the .cpp file.

I thought this was funny

While the above is real, here are some others

0xbaadc0de
0xcafefeed
0xc0deface
0xbaadf00d
0xbaadfeed

I didnt’ know this but Visual Studio 2008 has a GORGEOUS ribbon style that you can select when building an MFC app. Fully explore the project creation wizard when you build an MFC app, its worth it!

This was jaw-dropping, for me.

Understanding how to use extern variables in C/C++

Start with a visual studio project.

create 5 files, and copy/paste the contents as show below in them.

Alternatively, esnips code package! (thanks esnips!)

externVarDeclaration.h

#ifndef EXTERN_VAR_DECL_H
#define EXTERN_VAR_DECL_H

extern int i ;  // This is like a "function prototype", only
// for variables.

// The extern declaration says, "this variable doesn't exist yet,
// but it WILL exist, and its value is going to be defined
// in another file that will be part of this project when it compiles."
// (see externVarDefinition.cpp)

// So, using an EXTERN is how you share a single global variable
// ACROSS MULTIPLE FILES.
// Call it a SUPERGLOBAL.  TO understand this, think about
// functions and function prototypes.

// Defining a global function, you kind of expect it to have
// "superglobal" status..
// like, if you define a function somewhere, you should be
// able to break it apart into some prototypes and #include
// those prototypes in ANY FILE that you want
// to use those functions.  Right?

// So, the reason you have prototypes is so that multiple
// files can #include the same prototypes (function
// DECLARATIONS) then the actual code for the
// DEFINITION of the functions is in one place,
// a .cpp file (like "function_set.cpp").  This way you don't
// have multiple re-definitions of the functions declared in
// function_set.h, but you may have multiple re-declarations
// (the compiler might see the same prototype several times
// in a row, which is fine, as long as it sees the BODY
// definition only once.)

// So, an extern'd variable is a lot like that.
// You basically treat it like a function prototype, where the

///// extern int i ;

// part is the DECLARATION (like a function prototype),
// and the part in externVarDefinition.cpp:

// int i = 500 ;

// is like the DEFINITION, or function body.

// C++ can only come across the DEFINITION (value giving part) __ONCE__ for any
// given variable.

// So with externs, you can #include the "extern variable declaration" into as
// many files as you like (just like you can #include the function prototypes
// into as many different files as you wish), so long as
// the "DEFINITION" (the int i = 500 part) only occurs once, in one file.

// If you uncomment this line below, you will see
// its ILLEGAL.

//////////int j = 50 ; ////ILLEGAL

// Surprised?  Well, very illegal!

// Reason:  EVEN WITH the #ifndef #include guards
// on this file.. because this "externVarDeclaration.h" file is
// #included in more than one other file, for some reason the C++
// LINKER (__NOT__ the compiler) will flag it as an error:

// "int j" already defined in main.obj.

// One day I'd like to be able to fully understand why this is
// myself, but for now, "EXTERN solves this problem".

#endif //EXTERN_VAR_DECL_H

function_set.h

#ifndef FUNCTION_SET_H
#define FUNCTION_SET_H

#include <stdio.h>
#include "externVarDeclaration.h"

void print() ;
void print2() ;
void print3() ;
void changeI() ;

#endif //FUNCTION_SET_H

externVarDefinition.cpp

#include "externVarDeclaration.h"

int i = 500 ;

// HERE we define the VALUE of the extern'd variable i.

function_set.cpp

#include "function_set.h"

void print()
{
  printf("func1 %d\n", i);
}

void print2()
{
  printf("func2 %d\n", i);
}

void print3()
{
  printf("func3 %d\n", i);
}

void changeI()
{
  // i is shared across the whole project
  i = 2000402;
}

main.cpp

#include <stdio.h>

#include "externVarDeclaration.h"
#include "function_set.h"


int main()
{
  printf( "The extern'd var is %d\n", i ) ;

  i = 20 ;
  print();

  i = 333 ;
  print2();

  changeI();

  printf("My oh my!  the extern'd var has changed to %d\n", i ) ;
}

So, you’re trying to make an MFC app?

Just to show you how simple it CAN BE, here’s one:

#include <afxwin.h>

class App : public CWinApp
{
public:
  BOOL InitInstance() override 
  {
    this->m_pMainWnd = new CFrameWnd() ;
    ((CFrameWnd*)this->m_pMainWnd)->Create( NULL, TEXT("MFC example!" ) ) ;
    this->m_pMainWnd->ShowWindow( TRUE ) ;

    return TRUE ;
  }
};

App app ;

BEFORE COMPILING, YOU MUST DO THIS in the project’s property page (right click your project name in the “Solution Explorer” and select “Properties”)

  1. avoid redundant state information

uh, more to come

You can:


using System.Runtime.InteropServices;

...

public static void test( [In][Out] ref int something )
{
    something = 5 ;
}

Be sure to add the using statement as shown!

Note if you try and do:

public static void test( out ref int something )
{
    something = 5 ;
}

You get:

Error 1 A parameter cannot have all the specified modifiers; there are too many modifers on the parameter

OK, this one is a bit more complex, so start here, then go there.

WHY C# events

An EVENT in C# is simply a means to create a CHAIN of functions that will execute when something “happens” to an object.

OBJECT with published event
subscriber 1 subscriber 2 subscriber 3 subscriber 4 subscriber 5

EVENTS in C# follow the observer design pattern. The object that CONTAINS the “event” is the “PUBLISHER”, while all the objects that “attach a function” to the event are “subscribers” to that event.

Understanding C# custom events

As a prerequisite to understanding this, you must have already worked with normal events in C#, and built a couple of simple windowed applications using .NET. If not, go read up on them, also try this.

In fact, let me summarize the prereqs to understanding this article here:

  • Worked with events in C# normally before (windows forms applications)
  • Understands delegates

If you don’t have those prereqs, RUN AWAY!! This will not make any sense to you, especially if you don’t understand delegates at all.

Custom events are great!

The point of defining custom events in C# is to provide an EASY MECHANISM to have a chain of functions that will execute in rapid succession on your command.

The idea is this. You have an object, say a BUTTON. WHEN THAT BUTTON IS CLICKED by the user, you want some function to run. But wait, not just ONE function. You want SEVERAL functions to run. In rapid succession, one after the other. AND YOU WANT THEM TO RUN WHEN THE BUTTON IS CLICKED!

So here’s what you do. You define an EVENT

using System;


public class Button
{
  // Define the EVENT here.
  public event Action Pushed ;

  // NOTICE how we specify the ACTION delegate
  // in this declaration.

  // The ACTION delegate use means that 
  // the "Pushed" event accepts a chain of
  // functions to be attached to it that all have
  // NO arguments, and return type VOID.

  // You can use ANY DELEGATE TYPE YOU WANT for
  // an event in C#.  You can define your own
  // delegate type if you want, but you will really
  // have to study and understand delegates if you
  // want to do that (not covered here!)



  // This is the function that triggers the event.
  public void PushButton()
  {
    // Print out a message before actually firing the
    // Pushed event.
    Console.WriteLine("Oh, you pushed me.");
    
    // !! VERY IMPORTANT LINE!!
    Pushed();  // "FIRE" EVENT:  CAUSES ALL FUNCTIONS THAT WERE ATTACHED
    // TO THE "Pushed" EVENT PREVIOUSLY TO EXECUTE IN
    // RAPID SUCCESSION, ONE AFTER THE OTHER!

    // The funny thing about Events is the WEIRD, WEIRD, WEIRD
    // syntax is uses.  At one moment, you're +='ing to it,
    // the next moment, you're calling it as if it were a function.

    // Strictly speaking, the Pushed event ISN'T a function.
    // Its a series of functions.. internally it must be some
    // kind of object with some kind of linked list inside.  But
    // in any case, this notation takes some getting used to,
    // but once you're used to it, it makes a whole lotta sense.

    // ALSO, take note that YOU MUST "FIRE" THIS EVENT FROM
    // WITHIN THE Button CLASS!

    // YOU __CANNOT__ "FIRE" AN EVENT OUTSIDE THE CLASS IN WHICH
    // THAT EVENT IS DECLARED.  I explain this in more detail
    // below.

    // Finally, print out another message after firing all
    // event functions.
    Console.WriteLine("Great, now my paint is all dented");
  }
}


public class Program
{
  // one function that will be attached
  // to the Button's Pushed event.  Notice
  // it can be attached because it has
  // no arguments and return type void.
  public static void ButtonPusher()
  {
    Console.WriteLine("HI THERE!!");
  }

  // another function that will be attached
  // to the button's Pushed event
  public static void func2()
  {
    Console.WriteLine("HELLO!!");
  }

  // notice because of our use of the ACTION delegate
  // type in the Pushed event declaratino, we CANNOT
  // attach THIS functino to the Pushed event.  THe
  // signature of functions you attach to the Pushed event
  // MUST MATCH the signature of the delegate type you used
  // in the declaration of the event.  In this case the Pushed
  // event uses the Action delegate type, which is defined
  // in the .NET framework to be a delegate of return type void,
  // and accepts no arguments.
  public static void sayHi( int howMany )
  {
    Console.WriteLine( howMany + " hi's to yoU!" ) ;
  }

  static void Main( string[] args )
  {
    Button b = new Button();

    // Attach 3 functions to execute
    // when the Pushed event fires
    // from within the button
    b.Pushed += new Action( ButtonPusher );

    b.Pushed += new Action( func2 );

    b.Pushed += new Action( ButtonPusher );

    // Illegal:  sayHi does not match the Action delegate type,
    // and the Pushed event requires that the functions chained on
    // match the Action delegate type.
    ////////b.Pushed += new Action( sayHi ) ;

    // now push the button, (which in turn,
    // FIRES THE EVENT)
    b.PushButton();


    // Finally, notice this is illegal
    /////b.Pushed() ;
    // The error is:
    // Error 1 The event 'Button.Pushed' can only appear on the
    // left hand side of += or -= (except when used from
    // within the type 'Button')
    
    // Reason:  basically the EVENT member itself
    // is kind of private to the class.  You're not
    // allowed to "invoke it" from outside the Button class.

    // But you can, as we did here, define a function
    // within the Button class that in turn, invokes/fires
    // the event.

  }

}


I think events are rooted in the observer pattern, but you don’t have to know the observer pattern to apply what we’re working on here.

Ah, so, declaring a custom event in C# is fun. To summarize, here’s what you need:

1. A public delegate, which effectively specifies the type of function (argument list, return type) that can be chained onto the event. In this example, we just used the .NET defined Action delegate, which has return type void and no arguments passed to it.
2. Declaration of the event itself, inside the class that the event can “happen to”
3. Lastly, you TRIGGER the event from within the class in which the event is declared. You MAY NOT trigger the event from outside the class in which it is declared (you may NOT type eventName() OUTSIDE THE CLASS, EVER.)

Well, C# DOES have a typedef.

using Num = System.Int32 ;  // PRETTY MUCH typedef equivalent

static class Program
{
  static void Main()
  {
    Num x = 5 ;  // Num is completely equivalent to System.Int32;
    int y = 78 ;

  }
}

I KNOW I KNOW. But its MORE COMMON than you think.

I just was misguided on answers to TWO QUESTIONS in a row.. which I believed. One was the C# keyword IS equivalent in C++ doesn’t exist (which it does) and the other was there is no equivalent of keyword base in c++ (which there is).

There are all these noob posters on forums that .. post a wrong answer and .. there’s nobody to hold them accountable..

That said, who’s to say I’m not a noob poster.. I try my best to research problems I run into (guess how.. via the web).

The web isn’t all bad, just be careful, and don’t ever take the first response you get as CORRECT.

Equivalent of C# keyword is in C++

typeid()

Equivalent of C# keyword base in C++

BaseClassName::FunctionName()

Public vs private inheritance in C++

see

IS THERE an IS keyword in C++ like in C#?

YES, there is an IS keyword in C++. Just like in C#.

WRONG
WRONG

A few days ago I had this question and I saw this answer “NO” and I took it and accepted it.

Only today I saw in some sample code just use of typeid(). And guess what? typeid() turns BLUE in the IDE!


#include <iostream>
#include <string>
using namespace std;

class Entity
{
public:
  int hp ;
};

class Grunt : public Entity
{
public:
  string name ;
};

int main()
{
  Grunt grom ;
  grom.hp = 500 ;
  grom.name = "GROM HELLSCREAM!" ;

  const type_info * typeOfG = &typeid( grom ) ;

  cout << typeOfG->name() << endl;

  
  Entity wisp ;
  wisp.hp = 120 ;

  const type_info * typeOfWisp = &typeid( wisp ) ;

  cout << typeOfWisp->name() << endl; 


  // equivalent of C# is:
  //if( grom is Grunt )
  //{
  //}

  // accomplished by
  string classGrunt = "class Grunt" ;
  if( typeid(grom).name() == classGrunt )
  {
    cout << "Grom is a grunt" << endl;
  }
  else
  {
    cout << "Grom is NOT a grunt" << endl;
  }
 

  // so we coudl make this a bit more elegant by
#define is( obj, type ) typeid(obj).name()==type
  if( is( grom, classGrunt ) )
  {
    cout << "Grom is a grunt" << endl;
  }
  else
  {
    cout << "Grom is NOT a grunt" << endl;
  }
 
  /*
  class type_info {
    bool operator==( type_info rhs ) ;
    bool operator!=( type_info rhs ) ;
    int before( type_info rhs ) ;
    const char* name();
    const char* raw_name();
  } ;
  */
  
}