1271 } |
1271 } |
1272 ShowVehicleListWindowLocal(player, VLW_DEPOT_LIST, vehicle_type, depot_airport_index); |
1272 ShowVehicleListWindowLocal(player, VLW_DEPOT_LIST, vehicle_type, depot_airport_index); |
1273 } |
1273 } |
1274 |
1274 |
1275 |
1275 |
|
1276 /* Unified vehicle GUI - Vehicle Details Window */ |
|
1277 |
|
1278 /** Constants of vehicle details widget indices */ |
|
1279 enum VehicleDetailsWindowWidgets { |
|
1280 VLD_WIDGET_CLOSEBOX = 0, |
|
1281 VLD_WIDGET_CAPTION, |
|
1282 VLD_WIDGET_RENAME_VEHICLE, |
|
1283 VLD_WIDGET_TOP_DETAILS, |
|
1284 VLD_WIDGET_INCREASE_SERVICING_INTERVAL, |
|
1285 VLD_WIDGET_DECREASE_SERVICING_INTERVAL, |
|
1286 VLD_WIDGET_BOTTOM_RIGHT, |
|
1287 VLD_WIDGET_MIDDLE_DETAILS, |
|
1288 VLD_WIDGET_SCROLLBAR, |
|
1289 VLD_WIDGET_DETAILS_CARGO_CARRIED, |
|
1290 VLD_WIDGET_DETAILS_TRAIN_VEHICLES, |
|
1291 VLD_WIDGET_DETAILS_CAPACITY_OF_EACH, |
|
1292 VLD_WIDGET_DETAILS_TOTAL_CARGO, |
|
1293 VLD_WIDGET_RESIZE, |
|
1294 }; |
|
1295 |
|
1296 /** Vehicle details widgets. */ |
|
1297 static const Widget _vehicle_details_widgets[] = { |
|
1298 { WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, // VLD_WIDGET_CLOSEBOX |
|
1299 { WWT_CAPTION, RESIZE_RIGHT, 14, 11, 364, 0, 13, 0x0, STR_018C_WINDOW_TITLE_DRAG_THIS}, // VLD_WIDGET_CAPTION |
|
1300 { WWT_PUSHTXTBTN, RESIZE_LR, 14, 365, 404, 0, 13, STR_01AA_NAME, STR_NULL /* filled in later */}, // VLD_WIDGET_RENAME_VEHICLE |
|
1301 { WWT_PANEL, RESIZE_RIGHT, 14, 0, 404, 14, 55, 0x0, STR_NULL}, // VLD_WIDGET_TOP_DETAILS |
|
1302 { WWT_PUSHTXTBTN, RESIZE_TB, 14, 0, 10, 101, 106, STR_0188, STR_884D_INCREASE_SERVICING_INTERVAL}, // VLD_WIDGET_INCREASE_SERVICING_INTERVAL |
|
1303 { WWT_PUSHTXTBTN, RESIZE_TB, 14, 0, 10, 107, 112, STR_0189, STR_884E_DECREASE_SERVICING_INTERVAL}, // VLD_WIDGET_DECREASE_SERVICING_INTERVAL |
|
1304 { WWT_PANEL, RESIZE_RTB, 14, 11, 404, 101, 112, 0x0, STR_NULL}, // VLD_WIDGET_BOTTOM_RIGHT |
|
1305 { WWT_MATRIX, RESIZE_RB, 14, 0, 392, 56, 100, 0x701, STR_NULL}, // VLD_WIDGET_MIDDLE_DETAILS |
|
1306 { WWT_SCROLLBAR, RESIZE_LRB, 14, 393, 404, 56, 100, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, // VLD_WIDGET_SCROLLBAR |
|
1307 { WWT_PUSHTXTBTN, RESIZE_TB, 14, 0, 95, 113, 124, STR_013C_CARGO, STR_884F_SHOW_DETAILS_OF_CARGO_CARRIED}, // VLD_WIDGET_DETAILS_CARGO_CARRIED |
|
1308 { WWT_PUSHTXTBTN, RESIZE_TB, 14, 96, 194, 113, 124, STR_013D_INFORMATION, STR_8850_SHOW_DETAILS_OF_TRAIN_VEHICLES},// VLD_WIDGET_DETAILS_TRAIN_VEHICLES |
|
1309 { WWT_PUSHTXTBTN, RESIZE_TB, 14, 195, 293, 113, 124, STR_013E_CAPACITIES, STR_8851_SHOW_CAPACITIES_OF_EACH}, // VLD_WIDGET_DETAILS_CAPACITY_OF_EACH |
|
1310 { WWT_PUSHTXTBTN, RESIZE_RTB, 14, 294, 392, 113, 124, STR_013E_TOTAL_CARGO, STR_8852_SHOW_TOTAL_CARGO}, // VLD_WIDGET_DETAILS_TOTAL_CARGO |
|
1311 { WWT_RESIZEBOX, RESIZE_LRTB, 14, 393, 404, 113, 124, 0x0, STR_RESIZE_BUTTON}, // VLD_RESIZE |
|
1312 { WIDGETS_END}, |
|
1313 }; |
|
1314 |
|
1315 |
|
1316 /** Command indices for the _vehicle_command_translation_table. */ |
|
1317 enum VehicleStringTranslation { |
|
1318 VST_VEHICLE_AGE_RUNNING_COST_YR, |
|
1319 VST_VEHICLE_MAX_SPEED, |
|
1320 VST_VEHICLE_PROFIT_THIS_YEAR_LAST_YEAR, |
|
1321 VST_VEHICLE_RELIABILITY_BREAKDOWNS, |
|
1322 }; |
|
1323 |
|
1324 /** Command codes for the shared buttons indexed by VehicleCommandTranslation and vehicle type. */ |
|
1325 static const StringID _vehicle_translation_table[][4] = { |
|
1326 { // VST_VEHICLE_AGE_RUNNING_COST_YR |
|
1327 STR_885D_AGE_RUNNING_COST_YR, |
|
1328 STR_900D_AGE_RUNNING_COST_YR, |
|
1329 STR_9812_AGE_RUNNING_COST_YR, |
|
1330 STR_A00D_AGE_RUNNING_COST_YR, |
|
1331 }, |
|
1332 { // VST_VEHICLE_MAX_SPEED |
|
1333 STR_NULL, |
|
1334 STR_900E_MAX_SPEED, |
|
1335 STR_9813_MAX_SPEED, |
|
1336 STR_A00E_MAX_SPEED, |
|
1337 }, |
|
1338 { // VST_VEHICLE_PROFIT_THIS_YEAR_LAST_YEAR |
|
1339 STR_885F_PROFIT_THIS_YEAR_LAST_YEAR, |
|
1340 STR_900F_PROFIT_THIS_YEAR_LAST_YEAR, |
|
1341 STR_9814_PROFIT_THIS_YEAR_LAST_YEAR, |
|
1342 STR_A00F_PROFIT_THIS_YEAR_LAST_YEAR, |
|
1343 }, |
|
1344 { // VST_VEHICLE_RELIABILITY_BREAKDOWNS |
|
1345 STR_8860_RELIABILITY_BREAKDOWNS, |
|
1346 STR_9010_RELIABILITY_BREAKDOWNS, |
|
1347 STR_9815_RELIABILITY_BREAKDOWNS, |
|
1348 STR_A010_RELIABILITY_BREAKDOWNS, |
|
1349 }, |
|
1350 }; |
|
1351 |
|
1352 /** Initialize a newly created vehicle details window */ |
|
1353 void CreateVehicleDetailsWindow(Window *w) |
|
1354 { |
|
1355 const Vehicle *v = GetVehicle(w->window_number); |
|
1356 |
|
1357 switch (v->type) { |
|
1358 case VEH_TRAIN: |
|
1359 ResizeWindow(w, 0, 39); |
|
1360 |
|
1361 w->vscroll.cap = 6; |
|
1362 w->height += 12; |
|
1363 w->resize.step_height = 14; |
|
1364 w->resize.height = w->height - 14 * 2; // Minimum of 4 wagons in the display |
|
1365 |
|
1366 w->widget[VLD_WIDGET_RENAME_VEHICLE].tooltips = STR_8867_NAME_TRAIN; |
|
1367 w->widget[VLD_WIDGET_CAPTION].data = STR_8802_DETAILS; |
|
1368 break; |
|
1369 |
|
1370 case VEH_ROAD: { |
|
1371 w->widget[VLD_WIDGET_CAPTION].data = STR_900C_DETAILS; |
|
1372 w->widget[VLD_WIDGET_RENAME_VEHICLE].tooltips = STR_902E_NAME_ROAD_VEHICLE; |
|
1373 |
|
1374 if (!RoadVehHasArticPart(v)) break; |
|
1375 |
|
1376 /* Draw the text under the vehicle instead of next to it, minus the |
|
1377 * height already allocated for the cargo of the first vehicle. */ |
|
1378 uint height_extension = 15 - 11; |
|
1379 |
|
1380 /* Add space for the cargo amount for each part. */ |
|
1381 for (const Vehicle *u = v; u != NULL; u = u->Next()) { |
|
1382 height_extension += 11; |
|
1383 } |
|
1384 |
|
1385 ResizeWindow(w, 0, height_extension); |
|
1386 } break; |
|
1387 |
|
1388 case VEH_SHIP: |
|
1389 w->widget[VLD_WIDGET_RENAME_VEHICLE].tooltips = STR_982F_NAME_SHIP; |
|
1390 w->widget[VLD_WIDGET_CAPTION].data = STR_9811_DETAILS; |
|
1391 break; |
|
1392 |
|
1393 case VEH_AIRCRAFT: |
|
1394 ResizeWindow(w, 0, 11); |
|
1395 w->widget[VLD_WIDGET_RENAME_VEHICLE].tooltips = STR_A032_NAME_AIRCRAFT; |
|
1396 w->widget[VLD_WIDGET_CAPTION].data = STR_A00C_DETAILS; |
|
1397 break; |
|
1398 default: NOT_REACHED(); |
|
1399 } |
|
1400 |
|
1401 if (v->type != VEH_TRAIN) { |
|
1402 w->vscroll.cap = 1; |
|
1403 w->widget[VLD_WIDGET_MIDDLE_DETAILS].right += 12; |
|
1404 } |
|
1405 |
|
1406 w->widget[VLD_WIDGET_MIDDLE_DETAILS].data = (w->vscroll.cap << 8) + 1; |
|
1407 w->caption_color = v->owner; |
|
1408 |
|
1409 WP(w, vehicledetails_d).tab = 0; |
|
1410 } |
|
1411 |
|
1412 /** Checks whether service interval is enabled for the vehicle. */ |
|
1413 static bool inline IsVehicleServiceIntervalEnabled(const VehicleType vehicle_type) |
|
1414 { |
|
1415 switch (vehicle_type) { |
|
1416 case VEH_TRAIN: return _patches.servint_trains != 0; break; |
|
1417 case VEH_ROAD: return _patches.servint_roadveh != 0; break; |
|
1418 case VEH_SHIP: return _patches.servint_ships != 0; break; |
|
1419 case VEH_AIRCRAFT: return _patches.servint_aircraft != 0; break; |
|
1420 default: NOT_REACHED(); |
|
1421 } |
|
1422 } |
|
1423 |
|
1424 extern int GetTrainDetailsWndVScroll(VehicleID veh_id, byte det_tab); |
|
1425 extern void DrawTrainDetails(const Vehicle *v, int x, int y, int vscroll_pos, uint16 vscroll_cap, byte det_tab); |
|
1426 extern void DrawRoadVehDetails(const Vehicle *v, int x, int y); |
|
1427 extern void DrawShipDetails(const Vehicle *v, int x, int y); |
|
1428 extern void DrawAircraftDetails(const Vehicle *v, int x, int y); |
|
1429 |
|
1430 /** |
|
1431 * Draw the details for the given vehicle at the position (x,y) of the Details windows |
|
1432 * |
|
1433 * @param v current vehicle |
|
1434 * @param x The x coordinate |
|
1435 * @param y The y coordinate |
|
1436 * @param vscroll_pos (train only) |
|
1437 * @param vscroll_cap (train only) |
|
1438 * @param det_tab (train only) |
|
1439 */ |
|
1440 static inline void DrawVehicleDetails(const Vehicle *v, int x, int y, int vscroll_pos, uint vscroll_cap, byte det_tab) |
|
1441 { |
|
1442 switch (v->type) { |
|
1443 case VEH_TRAIN: DrawTrainDetails(v, x, y, vscroll_pos, vscroll_cap, det_tab); break; |
|
1444 case VEH_ROAD: DrawRoadVehDetails(v, x, y); break; |
|
1445 case VEH_SHIP: DrawShipDetails(v, x, y); break; |
|
1446 case VEH_AIRCRAFT: DrawAircraftDetails(v, x, y); break; |
|
1447 default: NOT_REACHED(); |
|
1448 } |
|
1449 } |
|
1450 |
|
1451 /** Repaint vehicle details window. */ |
|
1452 static void DrawVehicleDetailsWindow(Window *w) |
|
1453 { |
|
1454 const Vehicle *v = GetVehicle(w->window_number); |
|
1455 byte det_tab = WP(w, vehicledetails_d).tab; |
|
1456 |
|
1457 SetWindowWidgetDisabledState(w, VLD_WIDGET_RENAME_VEHICLE, v->owner != _local_player); |
|
1458 |
|
1459 if (v->type == VEH_TRAIN) { |
|
1460 DisableWindowWidget(w, det_tab + 9); |
|
1461 SetVScrollCount(w, GetTrainDetailsWndVScroll(v->index, det_tab)); |
|
1462 } |
|
1463 |
|
1464 SetWindowWidgetsHiddenState(w, v->type != VEH_TRAIN, |
|
1465 VLD_WIDGET_SCROLLBAR, |
|
1466 VLD_WIDGET_DETAILS_CARGO_CARRIED, |
|
1467 VLD_WIDGET_DETAILS_TRAIN_VEHICLES, |
|
1468 VLD_WIDGET_DETAILS_CAPACITY_OF_EACH, |
|
1469 VLD_WIDGET_DETAILS_TOTAL_CARGO, |
|
1470 VLD_WIDGET_RESIZE, |
|
1471 WIDGET_LIST_END); |
|
1472 |
|
1473 /* Disable service-scroller when interval is set to disabled */ |
|
1474 SetWindowWidgetsDisabledState(w, !IsVehicleServiceIntervalEnabled(v->type), |
|
1475 VLD_WIDGET_INCREASE_SERVICING_INTERVAL, |
|
1476 VLD_WIDGET_DECREASE_SERVICING_INTERVAL, |
|
1477 WIDGET_LIST_END); |
|
1478 |
|
1479 |
|
1480 SetDParam(0, v->index); |
|
1481 DrawWindowWidgets(w); |
|
1482 |
|
1483 /* Draw running cost */ |
|
1484 SetDParam(1, v->age / 366); |
|
1485 SetDParam(0, (v->age + 365 < v->max_age) ? STR_AGE : STR_AGE_RED); |
|
1486 SetDParam(2, v->max_age / 366); |
|
1487 SetDParam(3, v->GetDisplayRunningCost()); |
|
1488 DrawString(2, 15, _vehicle_translation_table[VST_VEHICLE_AGE_RUNNING_COST_YR][v->type], 0); |
|
1489 |
|
1490 /* Draw max speed */ |
|
1491 switch (v->type) { |
|
1492 case VEH_TRAIN: |
|
1493 SetDParam(2, v->GetDisplayMaxSpeed()); |
|
1494 SetDParam(1, v->u.rail.cached_power); |
|
1495 SetDParam(0, v->u.rail.cached_weight); |
|
1496 SetDParam(3, v->u.rail.cached_max_te / 1000); |
|
1497 DrawString(2, 25, (_patches.realistic_acceleration && v->u.rail.railtype != RAILTYPE_MAGLEV) ? |
|
1498 STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE : |
|
1499 STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED, 0); |
|
1500 break; |
|
1501 |
|
1502 case VEH_ROAD: |
|
1503 case VEH_SHIP: |
|
1504 case VEH_AIRCRAFT: |
|
1505 SetDParam(0, v->GetDisplayMaxSpeed()); |
|
1506 DrawString(2, 25, _vehicle_translation_table[VST_VEHICLE_MAX_SPEED][v->type], 0); |
|
1507 break; |
|
1508 |
|
1509 default: NOT_REACHED(); |
|
1510 } |
|
1511 |
|
1512 /* Draw profit */ |
|
1513 SetDParam(0, v->profit_this_year); |
|
1514 SetDParam(1, v->profit_last_year); |
|
1515 DrawString(2, 35, _vehicle_translation_table[VST_VEHICLE_PROFIT_THIS_YEAR_LAST_YEAR][v->type], 0); |
|
1516 |
|
1517 /* Draw breakdown & reliability */ |
|
1518 SetDParam(0, v->reliability * 100 >> 16); |
|
1519 SetDParam(1, v->breakdowns_since_last_service); |
|
1520 DrawString(2, 45, _vehicle_translation_table[VST_VEHICLE_RELIABILITY_BREAKDOWNS][v->type], 0); |
|
1521 |
|
1522 /* Draw service interval text */ |
|
1523 SetDParam(0, v->service_interval); |
|
1524 SetDParam(1, v->date_of_last_service); |
|
1525 DrawString(13, w->height - (v->type != VEH_TRAIN ? 11 : 23), _patches.servint_ispercent ? STR_SERVICING_INTERVAL_PERCENT : STR_883C_SERVICING_INTERVAL_DAYS, 0); |
|
1526 |
|
1527 switch (v->type) { |
|
1528 case VEH_TRAIN: |
|
1529 DrawVehicleDetails(v, 2, 57, w->vscroll.pos, w->vscroll.cap, det_tab); |
|
1530 break; |
|
1531 |
|
1532 case VEH_ROAD: |
|
1533 case VEH_SHIP: |
|
1534 case VEH_AIRCRAFT: |
|
1535 DrawVehicleImage(v, 3, 57, 0, 0, INVALID_VEHICLE); |
|
1536 DrawVehicleDetails(v, 75, 57, w->vscroll.pos, w->vscroll.cap, det_tab); |
|
1537 break; |
|
1538 |
|
1539 default: NOT_REACHED(); |
|
1540 } |
|
1541 } |
|
1542 |
|
1543 /** Message strings for renaming vehicles indexed by vehicle type. */ |
|
1544 static const StringID _name_vehicle_title[] = { |
|
1545 STR_8865_NAME_TRAIN, |
|
1546 STR_902C_NAME_ROAD_VEHICLE, |
|
1547 STR_9831_NAME_SHIP, |
|
1548 STR_A030_NAME_AIRCRAFT |
|
1549 }; |
|
1550 |
|
1551 /** Message strings for error while renaming indexed by vehicle type. */ |
|
1552 static const StringID _name_vehicle_error[] = { |
|
1553 STR_8866_CAN_T_NAME_TRAIN, |
|
1554 STR_902D_CAN_T_NAME_ROAD_VEHICLE, |
|
1555 STR_9832_CAN_T_NAME_SHIP, |
|
1556 STR_A031_CAN_T_NAME_AIRCRAFT |
|
1557 }; |
|
1558 |
|
1559 /** Window event hook for vehicle details. */ |
|
1560 static void VehicleDetailsWndProc(Window *w, WindowEvent *e) |
|
1561 { |
|
1562 switch (e->event) { |
|
1563 case WE_CREATE: |
|
1564 CreateVehicleDetailsWindow(w); |
|
1565 break; |
|
1566 |
|
1567 case WE_PAINT: |
|
1568 DrawVehicleDetailsWindow(w); |
|
1569 break; |
|
1570 |
|
1571 case WE_CLICK: { |
|
1572 switch (e->we.click.widget) { |
|
1573 case VLD_WIDGET_RENAME_VEHICLE: {// rename |
|
1574 const Vehicle *v = GetVehicle(w->window_number); |
|
1575 SetDParam(0, v->index); |
|
1576 ShowQueryString(STR_VEHICLE_NAME, _name_vehicle_title[v->type], 31, 150, w, CS_ALPHANUMERAL); |
|
1577 } break; |
|
1578 |
|
1579 case VLD_WIDGET_INCREASE_SERVICING_INTERVAL: // increase int |
|
1580 case VLD_WIDGET_DECREASE_SERVICING_INTERVAL: { // decrease int |
|
1581 int mod = _ctrl_pressed ? 5 : 10; |
|
1582 const Vehicle *v = GetVehicle(w->window_number); |
|
1583 |
|
1584 mod = (e->we.click.widget == VLD_WIDGET_DECREASE_SERVICING_INTERVAL) ? -mod : mod; |
|
1585 mod = GetServiceIntervalClamped(mod + v->service_interval); |
|
1586 if (mod == v->service_interval) return; |
|
1587 |
|
1588 DoCommandP(v->tile, v->index, mod, NULL, CMD_CHANGE_SERVICE_INT | CMD_MSG(STR_018A_CAN_T_CHANGE_SERVICING)); |
|
1589 } break; |
|
1590 |
|
1591 case VLD_WIDGET_DETAILS_CARGO_CARRIED: |
|
1592 case VLD_WIDGET_DETAILS_TRAIN_VEHICLES: |
|
1593 case VLD_WIDGET_DETAILS_CAPACITY_OF_EACH: |
|
1594 case VLD_WIDGET_DETAILS_TOTAL_CARGO: |
|
1595 SetWindowWidgetsDisabledState(w, false, |
|
1596 VLD_WIDGET_DETAILS_CARGO_CARRIED, |
|
1597 VLD_WIDGET_DETAILS_TRAIN_VEHICLES, |
|
1598 VLD_WIDGET_DETAILS_CAPACITY_OF_EACH, |
|
1599 VLD_WIDGET_DETAILS_TOTAL_CARGO, |
|
1600 e->we.click.widget, |
|
1601 WIDGET_LIST_END); |
|
1602 |
|
1603 WP(w, vehicledetails_d).tab = e->we.click.widget - 9; |
|
1604 SetWindowDirty(w); |
|
1605 break; |
|
1606 } |
|
1607 } break; |
|
1608 |
|
1609 case WE_ON_EDIT_TEXT: |
|
1610 if (!StrEmpty(e->we.edittext.str)) { |
|
1611 _cmd_text = e->we.edittext.str; |
|
1612 DoCommandP(0, w->window_number, 0, NULL, CMD_NAME_VEHICLE | CMD_MSG(_name_vehicle_error[GetVehicle(w->window_number)->type])); |
|
1613 } |
|
1614 break; |
|
1615 |
|
1616 case WE_RESIZE: |
|
1617 if (e->we.sizing.diff.x != 0) ResizeButtons(w, 9, 12); |
|
1618 if (e->we.sizing.diff.y == 0) break; |
|
1619 |
|
1620 w->vscroll.cap += e->we.sizing.diff.y / 14; |
|
1621 w->widget[VLD_WIDGET_MIDDLE_DETAILS].data = (w->vscroll.cap << 8) + 1; |
|
1622 break; |
|
1623 } |
|
1624 } |
|
1625 |
|
1626 /** Vehicle details window descriptor. */ |
|
1627 static const WindowDesc _vehicle_details_desc = { |
|
1628 WDP_AUTO, WDP_AUTO, 405, 113, 405, 113, |
|
1629 WC_VEHICLE_DETAILS, WC_VEHICLE_VIEW, |
|
1630 WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE, |
|
1631 _vehicle_details_widgets, |
|
1632 VehicleDetailsWndProc |
|
1633 }; |
|
1634 |
|
1635 /** Shows the vehicle details window of the given vehicle. */ |
|
1636 static void ShowVehicleDetailsWindow(const Vehicle *v) |
|
1637 { |
|
1638 DeleteWindowById(WC_VEHICLE_ORDERS, v->index); |
|
1639 DeleteWindowById(WC_VEHICLE_DETAILS, v->index); |
|
1640 AllocateWindowDescFront(&_vehicle_details_desc, v->index); |
|
1641 } |
|
1642 |
|
1643 |
1276 /* Unified vehicle GUI - Vehicle View Window */ |
1644 /* Unified vehicle GUI - Vehicle View Window */ |
1277 |
1645 |
1278 /** Constants of vehicle view widget indices */ |
1646 /** Constants of vehicle view widget indices */ |
1279 enum VehicleViewWindowWidgets { |
1647 enum VehicleViewWindowWidgets { |
1280 VVW_WIDGET_CLOSEBOX = 0, |
1648 VVW_WIDGET_CLOSEBOX = 0, |