# DI_USERCONTROL

The DI_USERCONTROL dialog item describes an user-defined control controlled completely by the plugin: initialize, draw etc.

    struct FarDialogItem
    {
      int Type          = DI_USERCONTROL
      int X1            = X1
      int Y1            = Y1
      int X2            = X2
      int Y2            = Y2
      int Focus         = User Defined
      CHAR_INFO *VBuf   = Virtual Draw Buffer
      DWORD Flags       = Flags
      int DefaultButton = 0
      char Data[512]    = User Defined
    };

Attention!

- This is an exemplary structure; read full description here.

### Virtual Draw Buffer

VBuf parameter points to an array of CHAR_INFO structures that contain characters and their attributes to be drawn in the dialog.

If VBuf is NULL, the plugin itself must draw the control using the Text service function when a DN_DRAWDLGITEM event comes.

If VBuf is not NULL, the plugin must fill the VBuf array when it receives the DN_DRAWDLGITEM event, and the dialog manager will then copy the contents of the buffer to the screen.

This is the typical scenario for using the DI_USERCONTROL (see the source code of Reversi plugin):

    // allocate memory for the virtual buffer before calling DialogEx
    #define DIM(Item) (((Item).X2-(Item).X1+1)*((Item).Y2-(Item).Y1+1))
    CHAR_INFO *VBuf=new CHAR_INFO[DIM(DialogItems[11])];
    DialogItems[11].VBuf=VBuf;
      .
      .
      .
    // in the dialog callback function
    struct FarDialogItem DialogItem;

    case DN_DRAWDLGITEM:
      if(Param1 == 11)
      {
        char Face[4]="   ";
        SMALL_RECT Rect;
        BYTE AddColor=0x00;

        // get coordinates of the dialog and description of the item
        Info.SendDlgMessage(hDlg,DM_GETDLGRECT,0,(LONG_PTR)&Rect);
        Info.SendDlgMessage(hDlg,DM_GETDLGITEM,11,(LONG_PTR)&DialogItem);

        // drawing the game field
        for(Y=0; Y < 8; ++Y)
        {
          for(X=0; X < 8; ++X)
          {
            // prepare one rectangle

            // if the cell is not used...
            if (GAME[0].Field[Y*8+X]==0)
              Face[1]=' ';
            // for the white player
            else if (GAME[0].Field[Y*8+X]==GAME[0].Pl1)
            {
              Face[1]=FaceWhite;
              AddColor=0x00;
            }
            // for the black player
            else if (GAME[0].Field[Y*8+X]==GAME[0].Pl2)
            {
              Face[1]=FaceBlack;
              AddColor=0x0F;
            }

            // if the memory couldn't be allocated,
            // draw with the Text function
            if(!DialogItem.VBuf)
            {
              Info.Text(Rect.Left+DialogItem.X1+X*3,
                       Rect.Top+DialogItem.Y1+Y,
                      ColorsPanel[Y&1][X&1]|AddColor,
                      Face);
            }
            else // if the memory was allocated, use virtual buffer
            {
              CHAR_INFO *VBuf=&DialogItem.VBuf[Y*8*3+X*3];

              VBuf[0].Char.AsciiChar=Face[0];
              VBuf[1].Char.AsciiChar=Face[1];
              VBuf[2].Char.AsciiChar=Face[2];

              VBuf[0].Attributes=
                 VBuf[1].Attributes=
                 VBuf[2].Attributes=ColorsPanel[Y&1][X&1]|AddColor;
            }
          }
        }
      }
      return TRUE;

### Flags

There are several flags applicable to the DI_USERCONTROL control:

Flag | Description
--- | ---
DIF_NOFOCUS | The user-defined dialog control cannot receive keyboard focus, but can handle other user events.
DIF_DISABLE | Disables user access to the control.
DIF_NOTCVTUSERCONTROL | do not convert characters (CHAR_INFO::Char) while writing the virtual buffer to the screen.

### Events

Event | Description
--- | ---
DN_DRAWDLGITEM | This event is sent to the dialog callback function just before the item is drawn.
DN_KEY | This event comes after the user has pressed a key in the dialog.
DN_MOUSECLICK | This event comes after the user has clicked a mouse button; coordinates are counted from upper left corner of the item
DN_KILLFOCUS | This event is sent before the button loses focus, if the flag DIF_NOFOCUS was not used.
DN_GOTFOCUS | This event is sent after the button has received keyboard focus, if the flag DIF_NOFOCUS was not used.

### Remarks

1. For a description of how to manage the text cursor in a user-defined dialog control, see DM_GETCURSORPOS or DM_SETCURSORPOS.
2. The DI_USERCONTROL item is not supported by the Dialog function.

See also:
FarDialogItem