***DISCLAIMER - Intellectual Rights***
I wrote this 100% from scratch. If you are going to post this on another forum I would like to be credited by having a link to this thread at the top of your post.

http://www.youtube.com/watch?v=WF4q9F4g3Gc
Menu Navigation: - Insert key = Toggle open/close state of menu
- 4 arrow keys = Navigate within the menu. When you've got a hack selected, use left arrow to decrement and right arrow to increment the value
Code Organization:- Implementing the Menu class
- Source file
- Header file
- Creating an instance of the Menu class & using its public methods
- Global variables
- Initializing Menu object & setting menu properties
- Polling for menu input
- Polling the current hack setting value
- Drawing the menu
I. Menu Implementation:
a) Source file: HackMenu.cpp
Code:
#include "HackMenu.h"
#include "d3d9.h"
#include <windows.h>
#include <vector>
#include <string>
using namespace std;
HackMenu::HackMenu(LPDIRECT3DDEVICE9 lpDev, int menuWidth, int menuHeight, int menuBorderWidth) //: m_pDev(lpDev)
{
m_pDev = lpDev;
menuEnabled = false;
boxWidth = menuWidth;
boxHeight = menuHeight;
borderWidth = menuBorderWidth;
D3DXCreateFont(m_pDev, 17, 7, FW_BOLD, 1, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, ANTIALIASED_QUALITY, DEFAULT_PITCH|FF_DONTCARE, "Arial", &fontMainMenu);
D3DXCreateFont(m_pDev, 14, 5, FW_BOLD, 1, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, ANTIALIASED_QUALITY, DEFAULT_PITCH|FF_DONTCARE, "Arial", &fontSubMenu);
mainMenuSelected=0;
subMenuSelected = -1;
}
void HackMenu::display()
{
if(menuEnabled)
{
for (int i = 0; i< mainMenus.size(); i++) //Create main menu's
{
menuBorderBox.x1 = i * boxWidth;
menuBorderBox.x2 = (i * boxWidth) + boxWidth;
menuBorderBox.y1 = 0;
menuBorderBox.y2 = boxHeight;
menuBodyBox.x1 = (i * boxWidth) + borderWidth;
menuBodyBox.x2 = (i * boxWidth) + (boxWidth - borderWidth);
menuBodyBox.y1 = borderWidth;
menuBodyBox.y2 = boxHeight-borderWidth;
menuBodyBoxRect.bottom = menuBodyBox.y2;
menuBodyBoxRect.left = menuBodyBox.x1;
menuBodyBoxRect.right = menuBodyBox.x2;
menuBodyBoxRect.top = menuBodyBox.y1;
if (mainMenuSelected == i && subMenuSelected != -1)
{
for (int j = 0; j<mainMenus.at(i).individualHacks.size(); j++) //Create sub-menu's/hack for each main menu
{
hackBorderBox.x1 = i * boxWidth;
hackBorderBox.x2 = (i * boxWidth) + boxWidth;
hackBorderBox.y1 = menuBorderBox.y2 + (j*boxHeight);
hackBorderBox.y2 = menuBorderBox.y2 + (j*boxHeight) + boxHeight;
hackBodyBox.x1 = (i * boxWidth) + borderWidth;
hackBodyBox.x2 = (i * boxWidth) + (boxWidth - borderWidth);
hackBodyBox.y1 = menuBorderBox.y2 + (j*boxHeight) + borderWidth;
hackBodyBox.y2 = menuBorderBox.y2 + (j*boxHeight) + (boxHeight-borderWidth);
hackBodyBoxRect.bottom = hackBodyBox.y2;
hackBodyBoxRect.left = hackBodyBox.x1;
hackBodyBoxRect.right = hackBodyBox.x2;
hackBodyBoxRect.top = hackBodyBox.y1;
if (subMenuSelected == j)
{
DrawBox(&hackBodyBox, &hackBorderBox, D3DCOLOR_ARGB(255,0,0,0), D3DCOLOR_ARGB(255,0,255,0));
} else {
DrawBox(&hackBodyBox, &hackBorderBox, D3DCOLOR_ARGB(120,0,255,0), D3DCOLOR_ARGB(120,0,255,0));
}
char hackNameAndValue[20];
strcpy(hackNameAndValue, mainMenus.at(i).individualHacks.at(j).hackName);
sprintf(hackNameAndValue, "%s = %i", hackNameAndValue, getHackStatus(i,j));
fontSubMenu->DrawTextA(NULL, hackNameAndValue, -1, &hackBodyBoxRect, (DT_VCENTER), D3DCOLOR_ARGB(255,160,32,240));
}
}
if(mainMenuSelected == i)
{
DrawBox(&menuBodyBox, &menuBorderBox, D3DCOLOR_ARGB(255,0,255,0), D3DCOLOR_ARGB(255,0,255,0));
} else {
DrawBox(&menuBodyBox, &menuBorderBox, D3DCOLOR_ARGB(255,0,0,0), D3DCOLOR_ARGB(100,255,0,0));
}
fontMainMenu->DrawTextA(NULL, mainMenus.at(i).menuName, -1, &menuBodyBoxRect, (DT_VCENTER | DT_CENTER), D3DCOLOR_ARGB(255,160,32,240));
}
}
}
void HackMenu::addMainMenu(char *menuName, int numberOfHacks, char *hackNames[], int hackValueDefaults[], int hackValueMaximums[])
{
vector<hack> hacksInMenu;
for (int i = 0; i< numberOfHacks; i++) {
hack newHack;
newHack.hackName = hackNames[i];
newHack.currentValue = hackValueDefaults[i];
newHack.maxValue = hackValueMaximums[i];
hacksInMenu.push_back(newHack);
}
mainMenu newMainMenu;
newMainMenu.menuName = menuName;
newMainMenu.individualHacks = hacksInMenu;
mainMenus.push_back(newMainMenu);
}
bool HackMenu::setHackValue(int menuNumber, int hackNumber, bool incrementValue)
{
if(incrementValue)
{
if((mainMenus.at(menuNumber).individualHacks.at(hackNumber).currentValue) == mainMenus.at(menuNumber).individualHacks.at(hackNumber).maxValue)
{
return false;
} else {
(mainMenus.at(menuNumber).individualHacks.at(hackNumber).currentValue)++;
}
} else {
if((mainMenus.at(menuNumber).individualHacks.at(hackNumber).currentValue) == 0)
{
return false;
} else {
(mainMenus.at(menuNumber).individualHacks.at(hackNumber).currentValue)--;
}
}
return true;
}
int HackMenu::getHackStatus(int menuNumber, int hackNumber)
{
return mainMenus.at(menuNumber).individualHacks.at(hackNumber).currentValue;
}
void HackMenu::getInput()
{
while(1)
{
if (GetAsyncKeyState(VK_INSERT)) menuEnabled = !menuEnabled;
if (menuEnabled) {
if (GetAsyncKeyState(VK_RIGHT))
{
if((mainMenuSelected != (mainMenus.size()-1)) && (subMenuSelected == -1)) mainMenuSelected++;
if (subMenuSelected != -1) setHackValue(mainMenuSelected, subMenuSelected, true);
}
if (GetAsyncKeyState(VK_LEFT))
{
if ((mainMenuSelected !=0) && (subMenuSelected == -1)) mainMenuSelected--;
if (subMenuSelected != -1) setHackValue(mainMenuSelected, subMenuSelected, false);
}
if (GetAsyncKeyState(VK_UP) && subMenuSelected != -1) subMenuSelected--;
if (GetAsyncKeyState(VK_DOWN) && subMenuSelected != (mainMenus.at(mainMenuSelected).individualHacks.size()-1)) subMenuSelected++;
}
Sleep(100);
}
}
void HackMenu::DrawBox(D3DRECT *mainDimensions, D3DRECT * borderDimensions, D3DCOLOR bgColor,D3DCOLOR borderColor)
{
m_pDev->Clear(1, borderDimensions, D3DCLEAR_TARGET, borderColor, 1.0f, 0);
m_pDev->Clear(1, mainDimensions, D3DCLEAR_TARGET, bgColor, 1.0f, 0);
}
b) Header file: HackMenu.h:
Code:
#pragma once
#include "d3d9.h"
#include <windows.h>
#include <vector>
using namespace std;
class HackMenu
{
public:
/******** PUBLIC FUNCTION PROTOTYPES *********/
HackMenu(LPDIRECT3DDEVICE9 lpDev, int menuWidth, int menuHeight, int borderWidth); //Menu object Constructor
void display(); //Display/render the menu
void getInput(); //Get keyboard input for menu manipulation
void HackMenu::addMainMenu(char *menuName, int numberOfHacks, char *hackNames[], int hackValueDefaults[], int hackValueMaximums[]); //Add new menu & respective sub-menus
int HackMenu::getHackStatus(int menuNumber, int hackNumber); //Get value of hack setting. Parameters = indicies (start @ 0)
private:
/******** PRIVATE FUNCTION PROTOTYPES *********/
bool HackMenu::setHackValue(int menuNumber, int hackNumber, bool incrementValue); //Set the value of hack setting
void DrawBox(D3DRECT *mainDimensions, D3DRECT * borderDimensions, D3DCOLOR bgColor,D3DCOLOR borderColor); //Draw box area for menus
/******** INTERNAL PRIVATE PROPERTIES *********/
bool menuEnabled; //Should menu be drawn?
LPDIRECT3DDEVICE9 m_pDev; //IDirect3DDevice9 Interface used for rendering
LPD3DXFONT fontMainMenu; //Main menu font
LPD3DXFONT fontSubMenu; //Sub-menu font
int mainMenuSelected; //Main menu currently selected
int subMenuSelected; //Sub-menu currently selected
int boxWidth, boxHeight, borderWidth; //Menu size parameters
/******** MENU STRUCTURE PROPERTIES/MEMBERS *********/
struct hack //Individual hack/ sub-menu
{
char *hackName;
int maxValue;
int currentValue;
};
struct mainMenu //Main menu w/ corresponding sub-menus/hacks
{
char *menuName;
vector<hack> individualHacks;
};
vector<mainMenu> mainMenus; //Vector list of all the main menus & their corresponding sub-menus/hacks
/******** MAIN MENU PROPERTIES *********/
D3DRECT menuBodyBox; //Main Body area
D3DRECT menuBorderBox; // Border around main body area
RECT menuBodyBoxRect; //Rect where the txt will be displayed
/******** SUB-MENU/HACK PROPERTIES *********/
D3DRECT hackBodyBox; //Main Body area
D3DRECT hackBorderBox; // Border around main body area
RECT hackBodyBoxRect; //Rect where the txt will be displayed
};
II. Using the menu
a) Declare the global variable in the source file in which you are using the menu:
Also include your Menu class in your source file by adding the following to the top:
Code:
#include "HackMenu.h"
b) Initialize Procedure: (I placed mine in the HRESULT CD3DManager::Initialize() method of my D3D startkit
Code:
hMenu = new HackMenu(m_pD3Ddev, 75, 25, 3);
char *hacks1[] = {"Hack1", "Hack2"};
char *hacks2[] = {"Hack3", "Hack4"};
char *hacks3[] = {"Hack5", "Hack6"};
char *hacks4[] = {"Hack7", "Hack8"};
int hackDefaults[] = {0,0};
int hackMaximums[] = {1,1};
hMenu->addMainMenu("Menu1", 2, hacks1, hackDefaults, hackMaximums);
hMenu->addMainMenu("Menu2", 2, hacks2, hackDefaults, hackMaximums);
hMenu->addMainMenu("Menu3", 2, hacks3, hackDefaults, hackMaximums);
hMenu->addMainMenu("Menu4", 2, hacks4, hackDefaults, hackMaximums);
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)getMenuInput, NULL, 0, 0);
The constructor for HackMenu() takes the following parameters in their respective order- LPDIRECT3DDEVICE9 pointer [Type: LPDIRECT3DDEVICE9 ]
- Width of each menu [Type: int]
- Height of each menu [Type: int]
- Width of the borders of the menu [Type: int]
The addMainMenu() method for adding hacks to the menu has the following parameters in their respective order- Menu name [Type: char*]
- Number of sub-menus/hacks in that menu [Type: int]
- Names of the individual hacks/sub-menus [Type: char *[] ]
- Hack default values [Type: int[] ]
- Hack maximum values [Type: int [] ]
c) Add this method to the source file in which you are using the menu:
Code:
void getMenuInput()
{
hMenu->getInput();
}
d) To use the current setting of a hack from the menu as a conditional expression in some method such as EndScene() you can do the following:
Code:
if ( hMenu->getHackStatus(menuNumber, hackNumber) == value)
{
//Do Something...
}
Where - menuNumber = index of the top menu (starts from 0 and goes to one minus the length) [Type: int]
- hackNumber = index of the hack from the specified top menu (starts from 0 and goes to one minus the length) [Type: int]
- value = value of the hack (ie: 0, 1, ...maxValue) [Type: int]
e) Add this inside of your EndScene() method (or anywhere else you like) to get the menu to actually draw on-screen