Home Page
+ Reply to Thread
Results 1 to 2 of 2

Thread: [D3D] Basic Menu with Multiple Sub-Menus

  1. #1

    Code [D3D] Basic Menu with Multiple Sub-Menus

    ***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:
    1. Insert key = Toggle open/close state of menu
    2. 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:
    1. Implementing the Menu class
      1. Source file
      2. Header file
    2. Creating an instance of the Menu class & using its public methods
      1. Global variables
      2. Initializing Menu object & setting menu properties
      3. Polling for menu input
      4. Polling the current hack setting value
      5. 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:
    Code:
    HackMenu *hMenu;
    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
    1. LPDIRECT3DDEVICE9 pointer [Type: LPDIRECT3DDEVICE9 ]
    2. Width of each menu [Type: int]
    3. Height of each menu [Type: int]
    4. 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
    1. Menu name [Type: char*]
    2. Number of sub-menus/hacks in that menu [Type: int]
    3. Names of the individual hacks/sub-menus [Type: char *[] ]
    4. Hack default values [Type: int[] ]
    5. 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

    Code:
    hMenu->display();
    Last edited by Mr. Hasselhoff; 03-14-2011 at 05:39 PM.


  2. #2
    Thought this was going to be HTML/CSS for some strange reason. Good job though.
    no...i dont have a sig

+ Reply to Thread

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)